/*
(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 <libraries/dos.h>
#include <exec/memory.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <dos/dos.h>
#include "/v.h"
#include "display.h"
#include "all.h"

void assignparenttotool(macro,parent)

struct MacroTool *macro;
struct Tool *parent;

{
    unsigned short index;
    struct Tool *tool;
    if (!(macro->tool.tooltype & TOOL_MACRO)) return;
    for (index = 0;index <6;index++) {
        tool = macro->macroline[index].toollist;
        for (;tool;tool = tool->next) {
            tool->parent = parent;
            if (tool->tooltype & TOOL_MACRO)
                assignparenttotool((struct MacroTool *)tool,parent);
        }
    }
}

static struct MacroTool *createmacrotool()

{
    struct MacroTool *tool;
    tool = (struct MacroTool *) AllocMem(sizeof(struct MacroTool),MEMF_CLEAR);
    if (tool)
        tool->tool.tooltype = TOOL_MACRO | TOOL_NORMAL;
    return(tool);
}

toolloop(tool,id)

struct MacroTool *tool;
long id;

{
    unsigned short index;
    struct Tool *scan;
    if (tool->tool.toolid == id) return(1);
    if (tool->tool.tooltype & TOOL_MACRO) {
        for (index = 0;index < 6; index++) {
            scan = tool->macroline[index].toollist;
            for (;scan;scan = scan->next) {
                if (toolloop((struct MacroTool *)scan,id)) return(1);
            }
        }
    }
    return(0);
}

void assigncliptotool(tool,clip)

struct MacroTool *tool;
struct Clip *clip;

{
    unsigned short index;
    struct Tool *scan;
    tool->tool.clip = clip;
    if (tool->tool.tooltype & TOOL_MACRO) {
        for (index = 0;index < 6; index++) {
            scan = tool->macroline[index].toollist;
            for (;scan;scan = scan->next) {
                assigncliptotool((struct MacroTool *)scan,clip);
            }
        }
    }
}

void assigntracktotool(tool,track)

struct MacroTool *tool;
struct Track *track;

{
    unsigned short index;
    struct Tool *scan;
    tool->tool.track = track;
    if (tool->tool.tooltype & TOOL_MACRO) {
        for (index = 0;index < 6; index++) {
            scan = tool->macroline[index].toollist;
            for (;scan;scan = scan->next) {
                assigntracktotool((struct MacroTool *)scan,track);
            }
        }
    }
}

static struct Tool *copytoollist(tool)

struct Tool *tool;

{
    struct Tool *new;
    struct Tool *top = 0;
    struct Tool *last = 0;
    for (;tool;tool = tool->next) {
        new = (struct Tool *) createtool(tool->toolmaster,tool);
        if (new) {
            if (top) last->next = new;
            else top = new;
            last = new;
            new->branch = 0;
            if (tool->branch) {
                new->branchindex = tool->branch->id;
            }
            else new->branchindex = 0;
        }
    }
    return(top);
}

static void connect(macro,tool)

struct MacroTool *macro;
struct Tool *tool;

{
    struct Tool *point;
    unsigned short index;
    for (index=0;index<6;index++) {
        point = macro->macroline[index].toollist;
        for (;point;point = point->next) {
            if (point->id == tool->branchindex) {
                tool->branch = point;
                return;
            }
        }
    }
}


struct Tool *createtoolcode(macro)

struct MacroTool *macro;

{
    struct MacroTool *new;
    short id = 1;
    unsigned short index;
    struct Tool *tool;
    long branchout = 0;
    if (!macro || !macro->intool) {
        return(0);
    }
    new = createmacrotool();
    if (!new) return(0);
    for (index = 0;index <6;index++) {
        tool = macro->macroline[index].toollist;
        for (;tool;tool = tool->next) {
            tool->id = id++;
        }
    }
    for (index = 0;index <6;index++) {
        new->macroline[index].toollist =
            copytoollist(macro->macroline[index].toollist);
    }
    for (index = 0;index <6;index++) {
        tool = new->macroline[index].toollist;
        for (;tool;tool = tool->next) {
            if (tool->branchindex) connect(new,tool);
            tool->parent = (struct Tool *) new;
            branchout |= (tool->tooltype & TOOL_MACROOUT);
        }
    }
    new->inline = macro->inline;
    new->intool = new->macroline[new->inline].toollist;
    new->tool.tooltype |= TOOL_MACRO;
    if (branchout) new->tool.tooltype |= TOOL_BRANCHOUT;
    return((struct Tool *)new);
}

extern struct Functions functions;

static struct Event *processeventcode(event)

struct Event *event;

{
    struct MacroTool *tool = (struct MacroTool *) event->tool;
    if (tool->intool) {
        event->tool = tool->intool;
        return(event);
    }
    freeevent(event);
    return(0);
}

static void deletetoolcode(macro)

struct MacroTool *macro;

{
    unsigned short index;
    struct Tool *tool, *next;
    for (index = 0;index <6;index++) {
        tool = macro->macroline[index].toollist;
        for (;tool;) {
            if (tool->tooltype & (TOOL_MACROOUT | TOOL_MACROBRANCH)) next = 0;
            else next = tool->next;
            deletetool(tool);
            tool = next;
        }
    }
    FreeMem((char *)macro,sizeof(struct MacroTool));
}


static struct Event *dummyouteventcode(event)

struct Event *event;

{
    struct Tool *tool = (struct Tool *) event->tool;
    if (tool->parent) {
        event->tool = tool->parent->next;
        return(event);
    }
    freeevent(event);
    return(0);
}

static struct Event *dummybrancheventcode(event)

struct Event *event;

{
    struct Tool *tool = (struct Tool *) event->tool;
    if (tool->parent) {
        event->tool = tool->parent->branch;
        return(event);
    }
    freeevent(event);
    return(0);
}

static struct Tool *createcode(tool)

struct Tool *tool;

{
    if (!tool) tool = (struct Tool *) AllocMem(sizeof (struct Tool),MEMF_CLEAR);
    else tool = 0;
    return(tool);
}

struct ToolMaster dummyout, dummybranch;
FARCALL extern struct Image branchoutimage;
FARCALL extern struct Image streamoutimage;

void initdummyoutmasters()

{
    memset((char *)&dummyout,0,sizeof(struct ToolMaster));
    dummyout.image = &streamoutimage;
    strcpy(dummyout.name,"Macro Out");
    dummyout.toolid = ID_MCOT;
    dummyout.tooltype = TOOL_NORMAL | TOOL_MACROOUT;
    dummyout.processevent = (event_cast)dummyouteventcode;
/*    dummyout.createtool = createcode;*/
    memset((char *)&dummybranch,0,sizeof(struct ToolMaster));
    dummybranch.image = &branchoutimage;
    strcpy(dummybranch.name,"Macro Branch Out");
    dummybranch.tooltype = TOOL_MACROBRANCH | TOOL_NORMAL;
    dummybranch.toolid = ID_MCBR;
    dummybranch.processevent = (event_cast)dummybrancheventcode;
/*    dummybranch.createtool = createcode;*/
}

static void removetoolcode(master)

struct MacroMaster *master;

{
    deletetoolcode(master->macro);
    FreeMem((char *)master->master.image->ImageData,144);
    FreeMem((char *)master->master.image,sizeof(struct Image));
    FreeMem((char *)master->master.upimage->ImageData,144);
    FreeMem((char *)master->master.upimage,sizeof(struct Image));
    FreeMem((char *)master,sizeof(struct MacroMaster));
}

static struct MacroTool *macrotool = 0;

static unsigned long scrollroutine(window,gadget,x,y)

struct Window *window;
struct Gadget *gadget;
unsigned long x,y;

{
    if (macrotool) {
        macrotool->toolsindent = x;
        drawmacrotools(window->RPort,macrotool,10,15);
    }
    return(x);
}

FARCALL extern struct NewWindow editmacroNewWindowStructure1;

static SAVEDS void editmacrotoolcode(macro)

struct MacroTool *macro;

{
    struct IntuiMessage *message;
    unsigned long class, code;
    short xx,yy;
    short mousex, mousey;
    struct Window *window;
    struct Gadget *gadget;
    struct Tool *tool;
    struct Tool *newtool;
    long toolcommand;
    unsigned long refresh;
    struct NewWindow *newwindow;
    /* geta4(); */
    tool = 0;
//    newtool = 0;
    toolcommand = 0;
    refresh = -1;
    if (macro->tool.touched & TOUCH_EDIT) {
        editmacroNewWindowStructure1.LeftEdge = macro->tool.left;
        editmacroNewWindowStructure1.TopEdge = macro->tool.top;
    }
    newwindow = (struct NewWindow *)
        DupeNewWindow(&editmacroNewWindowStructure1);
    if (!newwindow) return;
    newwindow->Screen = functions.screen;
    newwindow->Title = 0;
    newwindow->Flags |= BORDERLESS;
    newwindow->Flags &= ~0xF;
    newwindow->DetailPen = 0;
    newwindow->BlockPen = 0;
    window = (struct Window *) FlashyOpenWindow(newwindow);
    macro->tool.window = window;
    if (window) {
        EmbossWindowOn(window,WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
            macro->tool.toolmaster->name,40000,40000,0,0);
        macrotool = macro;
        FatEmbossedPropOn(window,7,2,4,(long_cast)scrollroutine,8,2);
        EmbossOn(window,1,0);
        for (;;) {
            if (tool && (toolcommand == TOOLCOMMAND_EDIT)) {
                calledit(tool);
                toolcommand = 0;
                refresh = 0;
            }
            if (refresh & DRAW_CTOOLS) {
                calcmacrotools(macro);
            }
            if (refresh & DRAW_TOOLS) {
                drawmacrotools(window->RPort,macro,10,15);
                setmacroscrollbar(window,macro);
            }
            refresh = 0;
            message = (struct IntuiMessage *) GetIntuiMessage(window);
            class = message->Class;
            code = message->Code;
            mousex = message->MouseX;
            mousey = message->MouseY;
            gadget = (struct Gadget *) message->IAddress;
            class = SystemGadgets(window,class,gadget,code);
            ReplyMsg((struct Message *)message);
            if (class == CLOSEWINDOW) break;
            else if (class == GADGETDOWN) {
                switch (gadget->GadgetID) {
                    case 1 :
                        xx = mousex - 8;
                        xx = xx / 24;
                        yy = mousey - 15;
                        yy = yy /12;
                        newtool = (struct Tool *)
                            selectmacrotool(macro,xx,yy);
                        if (newtool) {
                            if (!doscall(dragtool,window,0,newtool)) {
                                if (newtool == tool) {
                                    toolcommand = TOOLCOMMAND_EDIT;
                                    tool = newtool;
                                }
                                else {
                                    toolcommand = TOOLCOMMAND_SELECT;
                                    if (tool && tool->selected) {
                                        tool->selected = 0;
                                        drawtool(tool,window->RPort,tool->x,tool->y,12);
                                    }
                                    tool = newtool;
                                    tool->selected = 1;
                                    drawtool(tool,window->RPort,tool->x,tool->y,12);
                                }
                            }
                            else toolcommand = 0;
                        }
                        break;
                    case 2 :
                        macrotool = macro;
                        ShiftEmbossedProp(window,7,-1,0);
                        break;
                    case 4 :
                        macrotool = macro;
                        ShiftEmbossedProp(window,7,1,0);
                        break;
                    case 7 :
                        macrotool = macro;
                        DragEmbossedProp(window,7);
                        break;
                }
            }
        }
        for (xx = 0;xx < 6; xx++) {
            tool = macro->macroline[xx].toollist;
            for (;tool;tool = tool->next) {
                if (tool->inedit) closetool(tool);
            }
        }
        macro->tool.window = 0;
        macro->tool.left = window->LeftEdge;
        macro->tool.top = window->TopEdge;
        macro->tool.touched |= TOUCH_EDIT;
        EmbossOff(window,1);
        FatEmbossedPropOff(window,7,2,4);
        FlashyCloseWindow(window);
        DeleteNewWindow(newwindow);
    }
}

struct MacroMaster *createmacromaster()

{
    struct MacroMaster *master;
    struct Image *image;
    short *data;
    static long macroid = 0x4D435241;
    static short macrocount = 1;
    master = (struct MacroMaster *) AllocMem(sizeof(struct MacroMaster),MEMF_CLEAR);
    image = (struct Image *) AllocMem(sizeof(struct Image),MEMF_CLEAR);
    data = (short *) AllocMem(144,MEMF_CLEAR | MEMF_CHIP);
    image->Width = 24;
    image->Height = 12;
    image->Depth = 3;
    image->ImageData = data;
    image->PlanePick = 0x1F;
    image->PlaneOnOff = 0;
    master->master.image = image;
    image = (struct Image *) AllocMem(sizeof(struct Image),MEMF_CLEAR);
    data = (short *) AllocMem(144,MEMF_CLEAR | MEMF_CHIP);
    image->Width = 24;
    image->Height = 12;
    image->Depth = 3;
    image->ImageData = data;
    image->PlanePick = 0x1F;
    image->PlaneOnOff = 0;
    master->master.upimage = image;
#ifdef GERMAN
    strcpy(master->master.name,"Macro Tool Nr. ");
#else
    strcpy(master->master.name,"Macro Tool #");
#endif
    Itoa(macrocount++,&master->master.name[12],10);
    while (gettoolmaster(macroid)) macroid++;
    master->master.toolid = macroid;
    master->master.createtool = (Tool_cast)createtoolcode;
    master->master.edittool = (void_cast)editmacrotoolcode;
    master->master.processevent = (event_cast)processeventcode;
    master->master.deletetool = (void_cast)deletetoolcode;
    master->master.removetool = (void_cast)removetoolcode;
    master->master.tooltype = TOOL_MACRO | TOOL_NORMAL;
    master->macro = createmacrotool();
    master->macro->tool.toolmaster = (struct ToolMaster *) master;
    return(master);
}

struct MacroMaster *initmacromaster(master)

struct MacroMaster *master;

{
    master->master.createtool = (Tool_cast)createtoolcode;
    master->master.edittool = (void_cast)editmacrotoolcode;
    master->master.processevent = (event_cast)processeventcode;
    master->master.deletetool = (void_cast)deletetoolcode;
    master->master.removetool = (void_cast)removetoolcode;
    master->macro->tool.toolmaster = (struct ToolMaster *) master;
    return(master);
}
