/*
(c) Copyright 1988-1994 Microsoft Corporation.

Microsoft Bars&Pipes Professional Source Code License

This License governs use of the accompanying Software.  
Microsoft hopes you find this Software useful.

You are licensed to do anything you want with the Software. 

In return, we simply require that you agree:

1.      Not to remove any copyright notices from the Software.

2.      That the Software comes "as is", with no warranties.  
        None whatsoever. This means no implied warranty of merchantability or 
        fitness for a particular purpose or any warranty of non-infringement.  
        Also, you must pass this disclaimer on whenever you distribute the Software.

3.      That we will not be liable for any of those types of damages known as indirect, 
        special, consequential, or incidental related to the Software or this License, 
        to the maximum extent the law permits. Also, you must pass this limitation of 
        liability on whenever you distribute the Software.

4.      That if you sue anyone over patents that you think may apply to the Software 
        for that person’s use of the Software, your license to the Software ends automatically.

5.      That the patent rights Microsoft is licensing only apply to the Software, 
        not to any derivatives you make.

6.      That your rights under the License end automatically if you breach this in any way.
*/

#include "/CompilerSpecific.h"
#include <intuition/intuition.h>
#include <utility/tagitem.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <graphics/gfxmacros.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <string.h>
#include <dos/dos.h>
#include <stdio.h>
#include "/v.h"
#include "windows.h"
#include "display.h"
#include "all.h"
#include "edit.h"

#include "embosstags.h"

extern struct Functions functions;
FARCALL extern struct Image closeonimage;
FARCALL extern struct Image closeoffimage;
FARCALL extern struct Image sizeonimage;
FARCALL extern struct Image sizeoffimage;
extern char is20; /* is 2.0 or greater WorkBench? */

#include "windowimages.c"

extern short redpen;

struct EmbossStuff {
    struct Gadget *closegadget;
    struct Gadget *draggadget;
    struct Gadget *sizegadget;
    struct Gadget *backgadget;
    struct Gadget *frontgadget;
    struct Gadget *leftgadget;
    struct Gadget *rightgadget;
    struct Gadget *topgadget;
    struct Gadget *bottomgadget;
    struct Gadget *vscrollgadget;
    struct Gadget *hscrollgadget;
    struct Gadget *sizeupgadget;
    char extratext[100];
    short extraleft;
    short closeid;
    short dragid;
    short sizeid;
    short backid;
    short frontid;
    short leftid;
    short rightid;
    short topid;
    short bottomid;
    short vscrollid;
    short hscrollid;
    unsigned short leftindent;
    unsigned short topindent;
    short width, height;
    short normalwidth, normalheight;
    short normalleft, normaltop;
    char justdidtoback;
    struct TagList *tags;
};

#define CLOSEID         0xFFF
#define DRAGID          0xFFE
#define SIZEID          0xFFD
#define BACKID          0xFFC
#define FRONTID         0xFFB
#define LEFTID          0xFFA
#define RIGHTID         0xFF9
#define TOPID           0xFF8
#define BOTTOMID        0xFF7
#define HSCROLLID       0xFF6
#define VSCROLLID       0xFF5
#define SIZEUPID        0xFF4
#define SIZEDOWNID      0xFF3

long gettagvalue(struct TagItem *tags,long findtag)
{
  if (!tags) return(0);
  for(;;)
  {
    if(tags->ti_Tag==TAG_DONE)
        break;
    if(tags->ti_Tag==findtag)
        return (long)tags->ti_Data;
    ++tags;
  }
  return(0);
}

void DrawEmbossedRect(rp,l,t,r,b,on)

struct RastPort *rp;
short l,t,r,b;
short on;

{
    short hipen, lopen;
    if (on == 2) {
        hipen = 1;
        lopen = 0;
    }
    else if (on == 0) {
        hipen = 1;
        lopen = 3;
    }
    else {
        hipen = 3;
        lopen = 1;
    }
    SetDrMd(rp,JAM1);
    SetAPen(rp,hipen);
    Move(rp,l,b);
    Draw(rp,l,t);
    Draw(rp,r-1,t);
    Move(rp,l+1,t);
    Draw(rp,l+1,b - 1);
    SetAPen(rp,lopen);
    Move(rp,r,t);
    Draw(rp,r,b);
    Draw(rp,l+1,b);
    Move(rp,r - 1,t+1);
    Draw(rp,r - 1,b);
}

static void DrawNewEmbossedRect(rp,l,t,r,b,on)

struct RastPort *rp;
short l,t,r,b;
short on;

{
    SetDrMd(rp,JAM1);
    SetAPen(rp,1);
    Move(rp,l,b);
    Draw(rp,l,t);
    Draw(rp,r-1,t);
    Move(rp,r-3,t+2);
    Draw(rp,r-3,b-2);
    Move(rp,r-2,b-1);
    Draw(rp,l+2,b-1);
    SetAPen(rp,2);
    Move(rp,l+1,b-1);
    Draw(rp,l+1,t+1);
    Move(rp,l+2,t+1);
    Draw(rp,l+2,b-1);
    Move(rp,r-1,b-1);
    Draw(rp,r-1,t+1);
    Move(rp,r-2,t+1);
    Draw(rp,r-2,b-1);
    SetAPen(rp,3);
    Move(rp,l+3,b-2);
    Draw(rp,l+3,t+1);
    Draw(rp,r-3,t+1);
    Move(rp,r,t);
    Draw(rp,r,b);
    Draw(rp,l+1,b);
}

static void clearsizeborders(rp,r,b)

struct RastPort *rp;
short r,b;

{
    SetDrMd(rp,JAM1);
    SetAPen(rp,0);
    Move(rp,2,b);
    Draw(rp,r,b);
    Move(rp,2,b-1);
    Draw(rp,r,b-1);
    Draw(rp,r,0);
    Move(rp,r-1,0);
    Draw(rp,r-1,b);
    Move(rp,r-2,0);
    Draw(rp,r-2,b);
    Move(rp,r-3,0);
    Draw(rp,r-4,b);
}

SAVEDS  void DrawEmbossedWindow(window,on)

struct Window *window;
short on;

{
    struct RastPort *rp = window->RPort;
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    short width = window->Width - 1;
    short height = window->Height - 1;
    /* geta4(); */
    if (on == 2) {
        clearsizeborders(rp,stuff->width,stuff->height);
    }
    else {
        DrawNewEmbossedRect(rp,0,0,window->Width-1,window->Height-1,on);
        if (stuff) {
            stuff->width = width;
            stuff->height = height;
        }
    }
}

SAVEDS  void EmbossWindowOff(window)

struct Window *window;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    struct IntuiMessage *message;
    short count;
    /* geta4(); */
    if (stuff) {
        if (stuff->sizeupgadget && (stuff->sizeupgadget->GadgetID == SIZEDOWNID)) {
            SizeWindow(window,stuff->normalwidth - window->Width,
                stuff->normalheight - window->Height);
            MoveWindow(window,stuff->normalleft - window->LeftEdge,
                stuff->normaltop - window->TopEdge);
            for (count = 0;count < 10;count++) {
                Wait(-1);
                message = (struct IntuiMessage *) GetMsg(window->UserPort);
                if (message) {
                    if (message->Class == NEWSIZE) count = 10;
                    ReplyMsg((struct Message *)message);
                }
            }
        }
        if (stuff->closegadget) {
            RemoveGadget(window,stuff->closegadget);
            FreeMem((char *)stuff->closegadget,sizeof(struct Gadget));
        }
        if (stuff->draggadget) {
            EmbossOff(window,stuff->dragid);
            RemoveGadget(window,stuff->draggadget);
            if (stuff->draggadget->GadgetText) {
                FreeMem((char *)stuff->draggadget->GadgetText,sizeof(struct IntuiText));
            }
            FreeMem((char *)stuff->draggadget,sizeof(struct Gadget));
        }
        if (stuff->frontgadget) {
            RemoveGadget(window,stuff->frontgadget);
            FreeMem((char *)stuff->frontgadget,sizeof(struct Gadget));
        }
        if (stuff->backgadget) {
            RemoveGadget(window,stuff->backgadget);
            FreeMem((char *)stuff->backgadget,sizeof(struct Gadget));
        }
        if (stuff->sizeupgadget) {
            RemoveGadget(window,stuff->sizeupgadget);
            FreeMem((char *)stuff->sizeupgadget,sizeof(struct Gadget));
        }
        if (stuff->sizegadget) {
            RemoveGadget(window,stuff->sizegadget);
            FreeMem((char *)stuff->sizegadget,sizeof(struct Gadget));
        }
        if (stuff->leftgadget) {
            RemoveGadget(window,stuff->leftgadget);
            FreeMem((char *)stuff->leftgadget,sizeof(struct Gadget));
        }
        if (stuff->rightgadget) {
            RemoveGadget(window,stuff->rightgadget);
            FreeMem((char *)stuff->rightgadget,sizeof(struct Gadget));
        }
        if (stuff->hscrollgadget) {
            EmbossedPropOff(window,stuff->hscrollid);
            RemoveGadget(window,stuff->hscrollgadget);
            FreeMem((char *)stuff->hscrollgadget->SpecialInfo,sizeof(struct PropInfo));
            FreeMem((char *)stuff->hscrollgadget->GadgetRender,sizeof(struct Image));
            FreeMem((char *)stuff->hscrollgadget,sizeof(struct Gadget));
        }
        if (stuff->vscrollgadget) {
            EmbossedPropOff(window,stuff->vscrollid);
            RemoveGadget(window,stuff->vscrollgadget);
            FreeMem((char *)stuff->vscrollgadget->SpecialInfo,sizeof(struct PropInfo));
            FreeMem((char *)stuff->vscrollgadget->GadgetRender,sizeof(struct Image));
            FreeMem((char *)stuff->vscrollgadget,sizeof(struct Gadget));
        }
        if (stuff->topgadget) {
            RemoveGadget(window,stuff->topgadget);
            FreeMem((char *)stuff->topgadget,sizeof(struct Gadget));
        }
        if (stuff->bottomgadget) {
            RemoveGadget(window,stuff->bottomgadget);
            FreeMem((char *)stuff->bottomgadget,sizeof(struct Gadget));
        }
        FreeMem((char *)stuff,sizeof (struct EmbossStuff));
        window->UserData = 0;
    }
}

static void newsize(window)

struct Window *window;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    struct Gadget *gadget;
    short width,value;
    if (gadget = stuff->hscrollgadget) {
        gadget->LeftEdge = stuff->leftindent + 20;
        gadget->TopEdge = window->Height - 10;
        gadget->Width = window->Width - (stuff->leftindent + 62);
        gadget->Height = 7;
    }
    if (gadget = stuff->vscrollgadget) {
        gadget->LeftEdge = window->Width - 20;
        gadget->TopEdge = stuff->topindent + 10;
        gadget->Width = 14;
        gadget->Height = window->Height - (stuff->topindent + 31);
    }
    width = 0;
/*    if (gadget = stuff->frontgadget) {
        gadget->LeftEdge = window->Width - 24;
        width -= 20;
    }*/
    if (gadget = stuff->backgadget) {
        gadget->LeftEdge = window->Width - 24;
        width += 20;
    }
    if (gadget = stuff->sizeupgadget) {
        gadget->LeftEdge = window->Width - 44;
        width += 20;
    }
    if (gadget = stuff->draggadget) {
        if (stuff->closegadget) {
            width += 20;
            gadget->LeftEdge = 26;
        }
        else {
            gadget->LeftEdge = 6;
        }
        value = gettagvalue((struct TagItem *)stuff->tags,ET_DRAGSHRINK);
        gadget->TopEdge = 3;
        gadget->Width = window->Width - width - 12 - value;
        gadget->Height = 8;
    }
}

static void faderect(rp,l,t,r,b)

struct RastPort *rp;
short l,t,r,b;

{
    static short pattern[] = {
        0xAAAA,0x5555,0xAAAA,0x5555
    };
    short *oldpattern;
    short oldpatternsize;
    oldpatternsize = rp->AreaPtSz;
    oldpattern = rp->AreaPtrn;
    SetAfPt(rp,pattern,2);
    BNDRYOFF(rp);
    SetAPen(rp,2);
    SetBPen(rp,0);
    SetDrMd(rp,JAM1);
    RectFill(rp,l,t,r,b);
    SetAfPt(rp,oldpattern,oldpatternsize);
    rp->Flags |= AREAOUTLINE;
}

static void setsubpens(menuitem)

struct MenuItem *menuitem;

{
    struct IntuiText *itext;
    for (;menuitem;menuitem = menuitem->NextItem) {
        if (menuitem->Flags & ITEMTEXT) {
            itext = (struct IntuiText *) menuitem->ItemFill;
            itext->FrontPen = 3;
            itext->BackPen = 1;
            itext->DrawMode = JAM2;
        }
        if (menuitem->SubItem) setsubpens(menuitem->SubItem);
    }
}

void setmenupens(window)

struct Window *window;

{
    struct Menu *menu = window->MenuStrip;
    window->DetailPen = 3;
    window->BlockPen = 1;
    for (;menu;menu = menu->NextMenu) {
        setsubpens(menu->FirstItem);
    }
}

static void setgraytitle(struct Window *window,short id)

{
    struct Gadget *gadget = GetGadget(window,id);
    if (gadget) {
        if (gadget->GadgetText) gadget->GadgetText->FrontPen = 3;
        DrawEmbossed(window,id);
    }
}

SAVEDS  void EmbossWindowOn(window,flags,title,leftindent,topindent,hroutine,vroutine)

struct Window *window;
long flags;
char *title;
unsigned short leftindent;
unsigned short topindent;
long (*hroutine)();
long (*vroutine)();

{
    struct Gadget *gadget;
    struct IntuiText *itext;
    struct PropInfo *prop;
    struct Image *image;
    struct EmbossStuff *stuff;
    short minwidth, minheight;
    /* geta4(); */
    updatefilename(window);
    stuff = (struct EmbossStuff *)
        AllocMem(sizeof(struct EmbossStuff),MEMF_CLEAR);
    saxpointer(window);
    if (!stuff) return;
    window->UserData = (APTR) stuff;
    if (leftindent < 4) leftindent = 4;
    if ((flags & (WINDOWDEPTH | WINDOWDRAG)) && (topindent < 12)) {
        topindent = 12;
    }
    else if (topindent < 2) topindent = 2;
    stuff->leftindent = leftindent;
    stuff->topindent = topindent;
    ModifyIDCMP(window,GADGETDOWN | GADGETUP | ACTIVEWINDOW | INACTIVEWINDOW |
        RAWKEY | window->IDCMPFlags);
    setmenupens(window);
    if (flags & WINDOWSIZING) {
        gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
        stuff->sizegadget = gadget;
        if (gadget) {
            stuff->sizeid = SIZEID;
            gadget->GadgetID = SIZEID;
            ModifyIDCMP(window,NEWSIZE | window->IDCMPFlags);
            gadget->LeftEdge = -21;
            gadget->TopEdge = -10;
            gadget->Width = 18;
            gadget->Height = 9;
            gadget->Flags = GADGHIMAGE | GADGIMAGE | GRELBOTTOM | GRELRIGHT;
            gadget->Activation = RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE;
            gadget->GadgetType = SIZING;
            gadget->GadgetRender = (APTR) &sizeoffimage;
            gadget->SelectRender = (APTR) &sizeonimage;
            AddGadget(window,gadget,1);
            RefreshGList(gadget,window,0,1);
        }
        gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
        stuff->sizeupgadget = gadget;
        if (gadget) {
            stuff->frontid = SIZEUPID;
            gadget->GadgetID = SIZEUPID;
            gadget->TopEdge = 2;
            gadget->Width = 20;
            gadget->Height = 10;
            newsize(window);
            gadget->Flags = GADGHIMAGE | GADGIMAGE;
            gadget->Activation = RELVERIFY | GADGIMMEDIATE;
            gadget->GadgetType = BOOLGADGET;
            gadget->GadgetRender = (APTR) &sizeupoffimage;
            gadget->SelectRender = (APTR) &sizeuponimage;
            AddGadget(window,gadget,1);
            RefreshGList(gadget,window,0,1);
        }
        if (leftindent < (window->Width - 70)) {
            gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            stuff->leftgadget = gadget;
            if (gadget) {
                stuff->leftid = LEFTID;
                gadget->GadgetID = LEFTID;
                gadget->LeftEdge = leftindent;
                gadget->TopEdge = -10;
                gadget->Width = 18;
                gadget->Height = 9;
                gadget->Flags = GADGHIMAGE | GADGIMAGE | GRELBOTTOM;
                gadget->Activation = RELVERIFY | GADGIMMEDIATE;
                gadget->GadgetType = BOOLGADGET;
                gadget->GadgetRender = (APTR) &clickleftoffimage;
                gadget->SelectRender = (APTR) &clickleftonimage;
                AddGadget(window,gadget,1);
                RefreshGList(gadget,window,0,1);
            }
            gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            stuff->rightgadget = gadget;
            if (gadget) {
                stuff->rightid = RIGHTID;
                gadget->GadgetID = RIGHTID;
                gadget->LeftEdge = -39;
                gadget->TopEdge = -10;
                gadget->Width = 18;
                gadget->Height = 9;
                gadget->Flags = GADGHIMAGE | GADGIMAGE | GRELBOTTOM | GRELRIGHT;
                gadget->Activation = RELVERIFY | GADGIMMEDIATE;
                gadget->GadgetType = BOOLGADGET;
                gadget->GadgetRender = (APTR) &clickrightoffimage;
                gadget->SelectRender = (APTR) &clickrightonimage;
                AddGadget(window,gadget,1);
                RefreshGList(gadget,window,0,1);
            }
            gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            stuff->hscrollgadget = gadget;
            if (gadget) {
                stuff->hscrollid = HSCROLLID;
                gadget->GadgetID = HSCROLLID;
                gadget->Activation =  RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE;
                gadget->Flags = GADGHNONE;
                gadget->GadgetType = PROPGADGET;
                newsize(window);
                if (window->MinWidth < (stuff->leftindent + 82))
                    window->MinWidth = stuff->leftindent + 82;
                image = (struct Image *)
                    AllocMem(sizeof(struct Image),MEMF_CLEAR);
                prop = (struct PropInfo *)
                    AllocMem(sizeof(struct PropInfo),MEMF_CLEAR);
                if (prop && image) {
                    prop->Flags = AUTOKNOB | FREEHORIZ;
                    prop->HorizBody = 0xFFFF;
                    prop->VertBody = 0xFFFF;
                    prop->HorizPot = 0;
                    prop->VertPot = 0;
                    gadget->SpecialInfo = (APTR) prop;
                    gadget->GadgetRender = image;
                    gadget->Flags |= GADGIMAGE;
                    AddGadget(window,gadget,1);
                    EmbossedPropOn(window,gadget->GadgetID,hroutine,10,1);
                }
            }
        }
        if (topindent < (window->Height - 40)) {
            gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            stuff->topgadget = gadget;
            if (gadget) {
                stuff->topid = TOPID;
                gadget->GadgetID = TOPID;
                gadget->LeftEdge = -21;
                gadget->TopEdge = topindent;
                gadget->Width = 18;
                gadget->Height = 9;
                gadget->Flags = GADGHIMAGE | GADGIMAGE | GRELRIGHT;
                gadget->Activation = RELVERIFY | GADGIMMEDIATE;
                gadget->GadgetType = BOOLGADGET;
                gadget->GadgetRender = (APTR) &clickupoffimage;
                gadget->SelectRender = (APTR) &clickuponimage;
                AddGadget(window,gadget,1);
                RefreshGList(gadget,window,0,1);
            }
            gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            stuff->bottomgadget = gadget;
            if (gadget) {
                stuff->bottomid = BOTTOMID;
                gadget->GadgetID = BOTTOMID;
                gadget->LeftEdge = -21;
                gadget->TopEdge = -19;
                gadget->Width = 18;
                gadget->Height = 9;
                gadget->Flags = GADGHIMAGE | GADGIMAGE | GRELBOTTOM | GRELRIGHT;
                gadget->Activation = RELVERIFY | GADGIMMEDIATE;
                gadget->GadgetType = BOOLGADGET;
                gadget->GadgetRender = (APTR) &clickdownoffimage;
                gadget->SelectRender = (APTR) &clickdownonimage;
                AddGadget(window,gadget,1);
                RefreshGList(gadget,window,0,1);
            }
            gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            stuff->vscrollgadget = gadget;
            if (gadget) {
                stuff->vscrollid = VSCROLLID;
                gadget->GadgetID = VSCROLLID;
                gadget->Activation =  RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE;
                gadget->Flags = GADGHNONE;
                gadget->GadgetType = PROPGADGET;
                newsize(window);
                if (window->MinHeight < (stuff->topindent + 41))
                    window->MinHeight = stuff->topindent + 41;
                image = (struct Image *)
                    AllocMem(sizeof(struct Image),MEMF_CLEAR);
                prop = (struct PropInfo *)
                    AllocMem(sizeof(struct PropInfo),MEMF_CLEAR);
                if (prop && image) {
                    prop->Flags = AUTOKNOB | FREEVERT;
                    prop->VertBody = 0xFFFF;
                    prop->HorizBody = 0xFFFF;
                    prop->HorizPot = 0;
                    prop->VertPot = 0;
                    gadget->SpecialInfo = (APTR) prop;
                    gadget->GadgetRender = image;
                    gadget->Flags |= GADGIMAGE;
                    AddGadget(window,gadget,1);
                    EmbossedPropOn(window,gadget->GadgetID,vroutine,1,10);
                }
            }
        }
    }
    minwidth = 8;
    if (flags & WINDOWCLOSE) {
        minwidth += 20;
        gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
        stuff->closegadget = gadget;
        if (gadget) {
            stuff->closeid = CLOSEID;
            gadget->GadgetID = CLOSEID;
            gadget->LeftEdge = 4;
            gadget->TopEdge = 2;
            gadget->Width = 20;
            gadget->Height = 10;
            gadget->Flags = GADGHIMAGE | GADGIMAGE;
            gadget->Activation = RELVERIFY | GADGIMMEDIATE;
            gadget->GadgetType = BOOLGADGET;
            gadget->GadgetRender = (APTR) &closeoffimage;
            gadget->SelectRender = (APTR) &closeonimage;
            AddGadget(window,gadget,1);
            RefreshGList(gadget,window,0,1);
        }
    }
    if (flags & WINDOWDEPTH) {
        minwidth += 20;
        gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
        stuff->backgadget = gadget;
        if (gadget) {
            stuff->backid = BACKID;
            gadget->GadgetID = BACKID;
            newsize(window);
            gadget->TopEdge = 2;
            gadget->Width = 20;
            gadget->Height = 10;
            gadget->Flags = GADGHIMAGE | GADGIMAGE;
            gadget->Activation = RELVERIFY | GADGIMMEDIATE;
            gadget->GadgetType = BOOLGADGET;
            gadget->GadgetRender = (APTR) &tobackoffimage;
            gadget->SelectRender = (APTR) &tobackonimage;
            AddGadget(window,gadget,1);
            RefreshGList(gadget,window,0,1);
        }
    }
    if (flags & WINDOWDRAG) {
        minwidth += 20;
        gadget = (struct Gadget *) AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
        stuff->draggadget = gadget;
        if (gadget) {
            stuff->dragid = DRAGID;
            gadget->GadgetID = DRAGID;
            newsize(window);
            gadget->Flags = GADGHNONE;
            gadget->Activation =
                RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE;
            gadget->GadgetType = WDRAGGING;
            itext = (struct IntuiText *)
                AllocMem(sizeof(struct IntuiText),MEMF_CLEAR);
            if (itext) {
                itext->FrontPen = redpen;
                itext->DrawMode = JAM1;
                itext->LeftEdge = 4;
                itext->TopEdge = 0;
                itext->IText = title;
                window->Title = 0;
                gadget->GadgetText = itext;
            }
            AddGadget(window,gadget,1);
            EmbossOn(window,stuff->dragid,1);
        }
    }
    if (window->Flags & WINDOWACTIVE) {
        DrawEmbossedWindow(window,1);
        if (stuff->draggadget) SelectEmbossed(window,stuff->dragid,1);
    }
    else {
        DrawEmbossedWindow(window,0);
        if (stuff->draggadget) {
            setgraytitle(window,stuff->dragid);
        }
    }
    if (flags & (WINDOWDEPTH | WINDOWDRAG | WINDOWSIZING)) minheight = 14;
    else minheight = 4;
    if (flags & WINDOWSIZING) {
        minwidth += 20;
        minheight += 10;
    }
    if (minwidth > window->MinWidth) window->MinWidth = minwidth;
    if (minheight > window->MinHeight) window->MinHeight = minheight;
}

SAVEDS  void EmbossRequestOn(window,title)

struct Window *window;
char *title;

{
    short width = window->Width;
    /* geta4(); */
    window->DetailPen = 2;
    window->BlockPen = 2;
    saxpointer(window);
    SetRast(window->RPort,2);
    DrawEmbossedWindow(window,1);
    if (title) {
        SetAPen(window->RPort,redpen);
        SetDrMd(window->RPort,JAM1);
        width -= (strlen(title) << 3);
        width = width >> 1;
        Move(window->RPort,width,9);
        Text(window->RPort,title,strlen(title));
    }
}

SAVEDS  void RefreshEmbossedWindowFrame(window)

struct Window *window;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    /* geta4(); */
    DrawEmbossedWindow(window,window->Flags & WINDOWACTIVE);
    if (stuff->draggadget) DrawEmbossed(window,stuff->dragid);
    if (stuff->sizegadget) RefreshGList(stuff->sizegadget,window,0,1);
    if (stuff->frontgadget) RefreshGList(stuff->frontgadget,window,0,1);
    if (stuff->backgadget) RefreshGList(stuff->backgadget,window,0,1);
    if (stuff->sizeupgadget) RefreshGList(stuff->sizeupgadget,window,0,1);
    if (stuff->closegadget) RefreshGList(stuff->closegadget,window,0,1);
    if (stuff->leftgadget) RefreshGList(stuff->leftgadget,window,0,1);
    if (stuff->rightgadget) RefreshGList(stuff->rightgadget,window,0,1);
    if (stuff->topgadget) RefreshGList(stuff->topgadget,window,0,1);
    if (stuff->bottomgadget) RefreshGList(stuff->bottomgadget,window,0,1);
    if (stuff->hscrollgadget) DrawEmbossedPropNR(window,stuff->hscrollid);
    if (stuff->vscrollgadget) DrawEmbossedPropNR(window,stuff->vscrollid);
}

static void drawextratext(window)

struct Window *window;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    short left;
    if (stuff->extratext[0]) {
        left = strlen(stuff->extratext);
        left = left << 3;
        left = stuff->draggadget->LeftEdge + stuff->draggadget->Width - left;
        left -= 10;
        Move(window->RPort,left,9);
        SetAPen(window->RPort,0);
        SetDrMd(window->RPort,JAM1);
        Text(window->RPort,stuff->extratext,strlen(stuff->extratext));
    }
}

static void setautolocate(long *mark)
{
   if (functions.running)
   {
     *mark = functions.timenow;
     refreshtrackwindow(DRAW_MARKERS|DRAW_SEQUENCE);
   }
   else
   {
     *mark = functions.starttime;
     refreshtrackwindow(DRAW_MARKERS|DRAW_SEQUENCE);
   }
}

static void moveactivewindow(struct Screen *screen,long dx, long dy)
{
  struct Window *window = screen->FirstWindow;
  for (;window;window = window->NextWindow)
  {
    if (window->Flags & WINDOWACTIVE)
    {
      MoveWindow(window,-dx,-dy);
    }
  }
}

SAVEDS int SystemGadgets(window,class,gadget,code)

struct Window *window;
long class;
struct Gadget *gadget;
long code;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    unsigned short id;
    unsigned short maxwidth, maxheight;
    WORD dx, dy;
    short newleft, newtop;
    static char shift = 0;
    static char alt = 0;
    /* geta4(); */
    if (class == REFRESHWINDOW) {
        BeginRefresh(window);
        RefreshEmbossedWindowFrame(window);
        EndRefresh(window,0);
    }
    if (class == RAWKEY) {
        switch (code) {
            case 224: /*shift left up*/
            case 225: /*shift right up*/
              shift = 0;
              break;
            case 96: /*shift left down*/
            case 97: /*shift right down*/
              shift = 1;
              break;
            case 0x64: case 0x65: /* alt key down */
              alt = 1;
              break;
            case 0xE4: case 0xE5: /*alt key up*/
              alt = 0;
              break;
            case 90 : /* ( key */
              rewindff(window,NULL,1);
              break;
            case 91 : /* ) key */
              rewindff(window,NULL,0);
              break;
            case 0x0F : /* 0 on keypad */
                if (functions.running) {
                    transportcommand(TC_STOP,functions.timenow);
                }
                transportcommand(TC_START,0);
                return(0);
                break;
            case RK_I : /* I key for MIDI internal met. toggle */
                functions.clicking = !functions.clicking;
                updateobject(&functions.countdown,0);
                break;
            case RK_L : /* Toggle metronome lead in on and off */
                if (functions.countdown & METRO_COUNTDOWN)
                  functions.countdown &= ~METRO_COUNTDOWN;
                else functions.countdown |= METRO_COUNTDOWN;
                updateobject(&functions.countdown,0);
                break;
            case RK_M : /* M key */
                if ((long)currentwindow(WINDOW_MINI)) closewindow(WINDOW_MINI);
                else openwindow(WINDOW_MINI);
                break;
            case RK_O : /* O key for MIDI metronome toggle */
                if (functions.midiclick & 0x80)
                  functions.midiclick &= ~0x80;
                else functions.midiclick |= 0x80;
                updateobject(&functions.countdown,0);
                break;
            case RK_P : /* P key */
                if (functions.running) break;
                functions.punchenabled = !functions.punchenabled;
                if (functions.punchenabled) {
                    code = timetomeasure(0,functions.punchin);
                    if (!(functions.countdown & METRO_COUNTDOWN))
                      code -= functions.countdown & METRO_MEASUREMASK;
                    if (code < 0) code = 0;
                    transportcommand(TC_POSITION,measuretotime(0,code));
                }
                break;
            case RK_R : /* R key */
                if (functions.recording)
                    transportcommand(TC_RECORDOFF,functions.timenow);
                else transportcommand(TC_RECORDON,functions.timenow);
                return(0);
                break;
            case RK_V : /* V key for visual metronome */
                functions.seeclick = !functions.seeclick;
                updateobject(&functions.countdown,0);
                break;
            case 0x1D : /* 1 on keypad */
              if (shift)
                setautolocate((long *)&functions.markone);
              else autolocate(0);
              break;
            case 0x1E : /* 2 on keypad */
              if (shift)
                setautolocate((long *)&functions.marktwo);
              else autolocate(1);
              break;
            case 0x1F : /* 3 on keypad */
              if (shift)
                setautolocate((long *)&functions.markthree);
              else autolocate(2);
              break;
            case 0x2B : /* not on U.S. keybds */
            case 0x2D : /* 4 on keypad */
              if (shift)
                setautolocate((long *)&functions.markfour);
              else autolocate(3);
              break;
            case 0x2E : /* 5 - left edit flag */
              if (shift) setautolocate((long *)&functions.cutin);
              else autolocate(8);
              break;
            case 0x2F : /* 6 - right edit flag */
              if (shift) setautolocate((long *)&functions.cutout);
              else autolocate(9);
              break;
            case 0x5C : /* punch in (keypad key "/") */
              if (shift) setautolocate((long *)&functions.punchin);
              else autolocate(4);
              break;
            case 0x5D : /* punch out (keypad key "*") */
              if (shift) setautolocate((long *)&functions.punchout);
              else autolocate(5);
              break;
            case 0x4A : /* loop in (keypad key "-") */
              if (shift) setautolocate((long *)&functions.loopin);
              else autolocate(6);
              break;
            case 0x5E : /* loop out (keypad key "+") */
              if (shift) setautolocate((long *)&functions.loopout);
              else autolocate(7);
              break;
            case 0x43 : /* Enter on keypad */
                if (functions.running) {
                    transportcommand(TC_STOP,functions.timenow);
                }
                else transportcommand(TC_PLAY,0);
                return(0);
                break;
            case 0x4C : /* up arrow */
            case 0x4D : /* down arrow */
            case 0x4E : /* right arrow */
            case 0x4F : /* left arrow */
              if (is20 && alt && ((functions.flags & FLAGS_DOUBLEWIDTH) ||
                (functions.flags & FLAGS_DOUBLEHEIGHT))) /* scroll screen */
              {
                LONG width, height;
                struct Rectangle rect;
                ULONG screen_modeID;
                screen_modeID = GetVPModeID(&functions.screen->ViewPort);
                if (screen_modeID != INVALID_ID)
                {
                  if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT))
                  {
                    width = rect.MaxX-rect.MinX+1;
                    height = rect.MaxY-rect.MinY+1;
                    dx = dy = 0;
                    if (code == 0x4F) dx = width;
                    else if (code == 0x4E) dx = -width;
                    else if (code == 0x4D) dy = -height;
                    else
                    {
                      dy = height;
                    }
                    if ((dy > 0) && (functions.screen->TopEdge > -dy))
                    {
                      MoveScreen(functions.screen,dx,-functions.screen->TopEdge);
                      if (shift) moveactivewindow(functions.screen,dx,-functions.screen->TopEdge);
                    }
                    else
                    {
                      MoveScreen(functions.screen,dx,dy);
                      if (shift) moveactivewindow(functions.screen,dx,dy);
                    }
                    moveallicongadgets(-dx,-dy,width,height);
                    code = class = 0;
                  }
                }
              }
              break;
            case 56: /* comma - scroll left */
              if (window != functions.window)
                ShiftEmbossedPropOnce(window,stuff->hscrollid,-1,-1);
              break;
            case 57: /* period - scroll right */
              if (window != functions.window)
                ShiftEmbossedPropOnce(window,stuff->hscrollid,1,1);
              break;
            default :
              break;
        }
        return(class);
    }
    if (class == ACTIVEWINDOW) {
/*      if (functions.flags & FLAGS_WINDOWTOFRONT) WindowToFront(window);*/
        DrawEmbossedWindow(window,1);
        if (stuff->draggadget) {
            SelectEmbossed(window,stuff->dragid,1);
            drawextratext(window);
        }
    }
    else if (class == INACTIVEWINDOW) {
        DrawEmbossedWindow(window,0);
        if (stuff->draggadget) {
            setgraytitle(window,stuff->dragid);
            drawextratext(window);
        }
    }
    else if (class == GADGETDOWN) {
        id = gadget->GadgetID;
        if (id >= VSCROLLID) {
            class = 0;
            if (id == stuff->leftid) {
                ShiftEmbossedProp(window,stuff->hscrollid,-1,-1);
            }
            else if (id == stuff->rightid) {
                ShiftEmbossedProp(window,stuff->hscrollid,1,1);
            }
            else if (id == stuff->hscrollid) {
                DragEmbossedProp(window,id);
            }
            else if (id == stuff->topid) {
                ShiftEmbossedProp(window,stuff->vscrollid,-1,-1);
            }
            else if (id == stuff->bottomid) {
                ShiftEmbossedProp(window,stuff->vscrollid,1,1);
            }
            else if (id == stuff->vscrollid) {
                DragEmbossedProp(window,id);
            }
        }
    }
    else if (class == GADGETUP) {
        id = gadget->GadgetID;
        if (id >= VSCROLLID) {
            class = 0;
            if (gadget == stuff->closegadget) {
                class = CLOSEWINDOW;
            }
/*          else if (gadget == stuff->frontgadget) {
                WindowToFront(window);
            }*/
            else if (gadget == stuff->backgadget) {
                if (alt && (functions.flags & FLAGS_WINDOWTOFRONT)) {
                    WindowToBack(window);
                    stuff->justdidtoback = 1;
                }
                else {
                    if (window->RPort->Layer ==
                        functions.screen->LayerInfo.top_layer)
                        WindowToBack(window);
                    else
                    {
                      if (shift) WindowToBack(window);
                      else WindowToFront(window);
                    }
                }
            }
        }
        else if (id == SIZEUPID) {
            stuff->normalleft = window->LeftEdge;
            stuff->normaltop = window->TopEdge;
            stuff->normalwidth = window->Width;
            stuff->normalheight = window->Height;
            maxwidth = window->MaxWidth;
            if (maxwidth > window->WScreen->Width)
                maxwidth = window->WScreen->Width;
            maxheight = window->MaxHeight;
            if (maxheight > window->WScreen->Height)
                maxheight = window->WScreen->Height;
            if (maxwidth == window->MinWidth) newleft = window->LeftEdge;
            else newleft = 0;
            if (maxheight == window->MinHeight) newtop = window->TopEdge;
            else newtop = 0;
            MoveWindow(window,newleft-window->LeftEdge,newtop-window->TopEdge);
            SizeWindow(window,maxwidth - window->Width,maxheight - window->Height);
            stuff->sizeupgadget->GadgetRender = (APTR) &sizedownoffimage;
            stuff->sizeupgadget->SelectRender = (APTR) &sizedownonimage;
            stuff->sizeupgadget->GadgetID = SIZEDOWNID;
        }
        else if (id == SIZEDOWNID) {
            SizeWindow(window,stuff->normalwidth - window->Width,
                stuff->normalheight - window->Height);
            MoveWindow(window,stuff->normalleft - window->LeftEdge,
                stuff->normaltop - window->TopEdge);
            stuff->sizeupgadget->GadgetRender = (APTR) &sizeupoffimage;
            stuff->sizeupgadget->SelectRender = (APTR) &sizeuponimage;
            stuff->sizeupgadget->GadgetID = SIZEUPID;
        }
    }
    else if (class == NEWSIZE) {
/*      if (gadget = stuff->sizeupgadget) {
            if (gadget->GadgetID == SIZEDOWNID) {
                stuff->sizeupgadget->GadgetRender = (APTR) &sizeupoffimage;
                stuff->sizeupgadget->SelectRender = (APTR) &sizeuponimage;
                stuff->sizeupgadget->GadgetID = SIZEUPID;
            }
        }*/
        DrawEmbossedWindow(window,2);
        SetAPen(window->RPort,0);
        SetOPen(window->RPort,0);
        SetDrMd(window->RPort,JAM2);
        RectFill(window->RPort,24,2,window->Width - 3,11);
        if (stuff->leftgadget) {
            RectFill(window->RPort,stuff->leftindent,window->Height - 12,
                window->Width,window->Height);
            RectFill(window->RPort,stuff->leftindent,stuff->height - 11,
                stuff->width,stuff->height);
        }
        if (stuff->topgadget) {
            RectFill(window->RPort,stuff->width - 22,stuff->topindent,
                stuff->width,stuff->height);
            RectFill(window->RPort,window->Width - 24,stuff->topindent,
                window->Width,window->Height);
        }
        DrawEmbossedWindow(window,1);
        newsize(window);
        if (stuff->hscrollgadget) {
            EmbossOff(window,stuff->hscrollid);
            EmbossOn(window,stuff->hscrollid,0);
            DrawEmbossedPropNR(window,stuff->hscrollid);
        }
        if (stuff->vscrollgadget) {
            EmbossOff(window,stuff->vscrollid);
            EmbossOn(window,stuff->vscrollid,0);
            DrawEmbossedPropNR(window,stuff->vscrollid);
        }
        if (stuff->draggadget) {
            EmbossOff(window,stuff->dragid);
            EmbossOn(window,stuff->dragid,1);
            SelectEmbossed(window,stuff->dragid,1);
        }
        if (stuff->leftgadget) RefreshGList(stuff->leftgadget,window,0,1);
        if (stuff->rightgadget) RefreshGList(stuff->rightgadget,window,0,1);
        if (stuff->topgadget) RefreshGList(stuff->topgadget,window,0,1);
        if (stuff->bottomgadget) RefreshGList(stuff->bottomgadget,window,0,1);
        if (stuff->sizegadget) RefreshGList(stuff->sizegadget,window,0,1);
        if (stuff->sizeupgadget) RefreshGList(stuff->sizeupgadget,window,0,1);
        if (stuff->frontgadget) RefreshGList(stuff->frontgadget,window,0,1);
        if (stuff->backgadget) RefreshGList(stuff->backgadget,window,0,1);
    }
    if ((class != REFRESHWINDOW) && (class != INACTIVEWINDOW) &&
        (class != RAWKEY) && (class != INTUITICKS) && (class != MOUSEMOVE)) {
        if (alt && (functions.flags & FLAGS_WINDOWTOFRONT)) {
            if (!stuff->justdidtoback) {
                if (window->RPort->Layer != functions.screen->LayerInfo.top_layer) {
                    WindowToFront(window);
                }
            }
        }
        stuff->justdidtoback = 0;
    }
    return(class);
}

SAVEDS  void ModifyWindowProps(window,hpos,vpos,hrange,vrange,hbody,vbody)

struct Window *window;
unsigned long hpos,vpos,hrange,vrange,hbody,vbody;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    /* geta4(); */
    if (stuff->hscrollid) {
        ModifyEmbossedProp(window,HSCROLLID,hpos,0,hrange,0,hbody,0);
    }
    if (stuff->vscrollid) {
        ModifyEmbossedProp(window,VSCROLLID,0,vpos,0,vrange,0,vbody);
    }
}

void EmbossedWindowTitle(window,title)

struct Window *window;
char *title;

{
    struct IntuiText *text;
    struct Gadget *gadget = GetGadget(window,DRAGID);
    if (gadget) {
        text = gadget->GadgetText;
        if (text) {
            text->IText = title;
            RefreshEmbossedWindowFrame(window);
        }
    }
}

SAVEDS  void EmbossedWindowText(window,text,left)

struct Window *window;
char *text;
short left;

{
    struct EmbossStuff *stuff = (struct EmbossStuff *) window->UserData;
    /* geta4(); */
    if (text) {
        memcpy(stuff->extratext,text,99);
        if (!left) {
            left = strlen(text);
            left = left << 3;
            left = stuff->draggadget->LeftEdge + stuff->draggadget->Width - left;
            left -= 10;
        }
        stuff->extraleft = left;
    }
    else stuff->extratext[0] = 0;
    DrawEmbossed(window,stuff->dragid);
    drawextratext(window);
}
