/*bugs list/things to do*/

/* 1: read palette from disk*/ -> I'm just waiting for the new palette (or super_picture) AFC class
/* 2: intermediary links*/     -> to be ready
/*!3: some memory is lost everytime!*/

/*unreferenced:
 *cl: <logic_c_dragquery>:  The class isn't used
 *obj:<logic_c_dragquery>:  the object isn't used
 *st: <closeFunc>:          An argument is required for a CallBack Hook
 *st: <delFunc>:            An argument is required for a CallBack Hook
 *h:  <layoutFunc>:         The Hook isn't used
 *app:<pressFunc>:          The Application address isn't used.
*/
OPT PREPROCESS,LARGE,OSVERSION=39
                                        /*boutton of the macro library*/
#define MUIimage(btmap) BitmapObject, \
    MUIA_FixWidth,27, \
    MUIA_FixHeight,27, \
    MUIA_Bitmap_Bitmap,btmap, \
    MUIA_Bitmap_Width,27, \
    MUIA_Bitmap_Height,27, \
    MUIA_Bitmap_MappingTable,mapping_table,\
    MUIA_Draggable,MUI_TRUE, End
                                        /*command boutton*/
#define button(btmap) BitmapObject, \
    ButtonFrame,\
    MUIA_FixWidth,27, \
    MUIA_FixHeight,27, \
    MUIA_Bitmap_Bitmap,btmap, \
    MUIA_Bitmap_Width,27, \
    MUIA_Bitmap_Height,27, \
    MUIA_InputMode,MUIV_InputMode_RelVerify,\
    MUIA_Bitmap_MappingTable,mapping_table,End
                                        /*objects in project windows*/
#define case(btmap) BitmapObject, ButtonFrame,MUIA_Draggable,MUI_TRUE,\
    MUIA_InputMode,MUIV_InputMode_RelVerify,\
    MUIA_FixWidth,27, \
    MUIA_FixHeight,27, \
    MUIA_Bitmap_Bitmap,btmap, \
    MUIA_Bitmap_Width,27, \
    MUIA_Bitmap_Height,27, \
    MUIA_Bitmap_MappingTable,mapping_table,\
    End

MODULE 'utility/tagitem','utility','utility/hooks','tools/installhook',
       'libraries/gadtools','libraries/asl','asl',
       'muimaster','libraries/mui','libraries/muip','mui/muicustomclass',
       'amigalib/boopsi',
       'intuition/classes','intuition/classusr','intuition/intuition','intuition/screens',
       'graphics/rastport',
       'exec/lists',
       'afc/DirList','afc/super_picture','graphics/gfx','afc/palette',
       'tools/exceptions'

OBJECT macro
    nin,ins:PTR TO LONG -> Pixels from the top /*Currently not used*/
    nout,outs:PTR TO LONG
    inOM -> OM = ON_MACRO
    outOM
    values:PTR TO LONG
    gad -> In the list
    name:PTR TO CHAR
    pictures[4]:ARRAY OF LONG
ENDOBJECT
OBJECT objet
    x,y                 -> 0-1000
    gad                 -> in a window
    ins:PTR TO LONG     -> points to the objects
    ind:PTR TO LONG     -> Number of the output of the source object
    state               -> switches
    value               -> outputs including light
    macro               -> adress of the used macro (NOT THE NUMBER)
ENDOBJECT

DEF screent,initialized, ->Classes
    app,
    waitwindow,wgauge,wtext,
    prefswin,poppen,selpen,prefs, startpen:PTR TO mui_penspec,fatwires,befat,
    cwindow, /*Last selected window, used by the tools (save)*/
    background,/*newx,newy,*/select,zone,requested,
    toolswin,macrolist,rectangle,nextid=1,
        mcrin,mcrinA,mcrout,mcroutA,mcrsave,
        bind,newwin,load:PTR TO object,save,
    nmIn[10]:ARRAY OF LONG,nmNin,nmOut[10]:ARRAY OF LONG,nmNout,nmIna,nmOuta,nmMacro:PTR TO macro,
    sigs=0,running,result,mode,source:PTR TO objet,sourced,sourceg,
    t:PTR TO LONG,s[200]:STRING,u,v,/*TEMPORARY values, not used to save a value!*/
    macros:PTR TO LONG,nmacros,
    filereq:PTR TO filerequester,
    layoutHook:hook,    /* for logic_c.mcc*/
    pressHook:hook,     /* for the included objects*/
    closeHook:hook,     /* close the active window*/
    delHook:hook,       /* delete objects*/
    dl=NIL:PTR TO dirlist,
    pic=NIL:PTR TO super_picture,/*pal=NIL:PTR TO palette,r,g,b,*/
    paltte:PTR TO LONG,
    systgads[10]:ARRAY OF LONG,     /*contains the addresses of the used super_bitmaps for the system gadgets*/
    systbmps[10]:ARRAY OF LONG,     /*contains the addresses of the corresponding bitmaps*/
    files[4]:ARRAY OF LONG,
    initx1,inity1,initx2,inity2, -> selection's position before change,to know
                                 -> how to move pieces
    pspec[32]:STRING,val,mapping_table[256]:ARRAY OF CHAR,to_release[256]:ARRAY OF LONG
DEF cl_pitem=NIL:PTR TO mui_customclass

CONST ATTR_WIREPEN=$8022,ATTR_SELCPEN=$8023,FL_NODRAW=1
ENUM ID_BIND=1,ID_NEWWIN,ID_LOAD,ID_SAVE,ID_CLOSEP,ID_MCRIN,ID_MCRINA,ID_MCROUT,ID_MCROUTA,ID_MCRSAVE
/*mode's value, to know the actiob when an object is clicked*/
ENUM MD_NONE=0,MD_BEGIN,MD_FINISH,MD_IN,MD_INA,MD_OUT,MD_OUTA
ENUM DR_NONE=0,DR_NORM,DR_COMPL /*type of drawing to do*/

/******************************
**  Logic_c class            **
******************************/
OBJECT logic_c_data
    wirespec:mui_penspec,wire,wirechange
    selcspec:mui_penspec,selc,selcchange
    x1,y1,x2,y2             /*finished selection*/
    ax1,ay1,ax2,ay2,modA    /*mod: DR_* */
    bx1,by1,bx2,by2,modB    /*AB xy 12 : 0-1000*/
    objs:PTR TO LONG,nobjs,temp /*temp is the RectangleObject put when the group's empty*/
    layoutr                 /*layoutr is the RectangleObject showed/hidden when objects moved (see relayout())*/
    window -> MUIA_WindowObject doesn't work!!
    changed
ENDOBJECT

DEF tgad,tdt:PTR TO logic_c_data

DEF cl_logic_c =NIL: PTR TO mui_customclass

PROC logic_c_new(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO opset)
DEF data:PTR TO logic_c_data,
    tags:PTR TO tagitem,
    tag:PTR TO tagitem

    IF (obj:=doSuperMethodA(cl,obj,msg))=NIL THEN RETURN 0

    data:=INST_DATA(cl_logic_c.mcc_class,obj)

    /* parse initial taglist */
    tags:=msg.attrlist
    WHILE tag:=NextTagItem({tags})
        IF tag.tag=ATTR_WIREPEN
            IF tag.data THEN CopyMem(tag.data,data.wirespec,SIZEOF mui_penspec)
        ELSEIF tag.tag=ATTR_SELCPEN
            IF tag.data THEN CopyMem(tag.data,data.selcspec,SIZEOF mui_penspec)
        ENDIF
    ENDWHILE
    data.modA:=DR_NONE;data.modB:=DR_NONE
    data.x1:=-1;data.x2:=-1;data.y1:=-1;data.y2:=-1
ENDPROC obj

PROC logic_c_set(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO opset)
DEF data:PTR TO logic_c_data,
    tags:PTR TO tagitem,
    tag:PTR TO tagitem

    data:=INST_DATA(cl,obj)
    tags:=msg.attrlist
    WHILE tag:=NextTagItem({tags})
        IF tag.tag=ATTR_WIREPEN
            IF tag.data
                CopyMem(tag.data,data.wirespec,SIZEOF mui_penspec)
                data.wirechange:=TRUE
                Mui_Redraw(obj,MADF_DRAWUPDATE)
            ENDIF
        ELSEIF tag.tag=ATTR_SELCPEN
            IF tag.data
                CopyMem(tag.data,data.selcspec,SIZEOF mui_penspec)
                data.selcchange:=TRUE
                Mui_Redraw(obj,MADF_DRAWUPDATE)
            ENDIF
        ENDIF
    ENDWHILE
ENDPROC doSuperMethodA(cl,obj,msg)

PROC logic_c_get(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO opget)
DEF data:PTR TO logic_c_data,storage
    IF msg.attrid=ATTR_WIREPEN
        data:=INST_DATA(cl,obj);storage:=msg.storage;^storage:=data.wirespec;RETURN MUI_TRUE
    ELSEIF msg.attrid=ATTR_WIREPEN
        data:=INST_DATA(cl,obj);storage:=msg.storage;^storage:=data.selcspec;RETURN MUI_TRUE
    ENDIF
ENDPROC doSuperMethodA(cl,obj,msg)

PROC logic_c_setup(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
DEF data:PTR TO logic_c_data
  IF doSuperMethodA(cl,obj,msg)=FALSE THEN RETURN FALSE
  data:=INST_DATA(cl,obj)
  data.wire:=Mui_ObtainPen(muiRenderInfo(obj),data.wirespec,0)
  data.selc:=Mui_ObtainPen(muiRenderInfo(obj),data.selcspec,0)
  Mui_RequestIDCMP(obj,IDCMP_MOUSEBUTTONS)
ENDPROC MUI_TRUE

PROC logic_c_cleanup(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
DEF data:PTR TO logic_c_data
  data:=INST_DATA(cl,obj)
  Mui_ReleasePen(muiRenderInfo(obj),data.wire)
  Mui_ReleasePen(muiRenderInfo(obj),data.selc)
  Mui_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS)
ENDPROC doSuperMethodA(cl,obj,msg)

PROC logic_c_handleinput(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_handleinput)
#define _between(a,x,b) (((x)>=(a)) AND ((x)<=(b)))
#define _isinobject(x,y) (_between(_mleft(obj),(x),_mright(obj)) AND _between(_mtop(obj),(y),_bottom(obj)))
DEF data:PTR TO logic_c_data,rx,ry,rw,rh,objs:PTR TO LONG,nobjs,z,optr:PTR TO objet,
idcmp,newx,newy,moved=FALSE

    background:=TRUE
    doSuperMethodA(cl,obj,msg)
    IF background
        data:=INST_DATA(cl,obj)

        objs:=data.objs;nobjs:=data.nobjs

        get(obj,MUIA_LeftEdge,{rx});get(obj,MUIA_TopEdge,{ry})
        get(obj,MUIA_Width,{rw});get(obj,MUIA_Height,{rh})

        IF msg.imsg
            idcmp:=msg.imsg.class
            SELECT idcmp
            CASE IDCMP_MOUSEBUTTONS
                IF msg.imsg.code=SELECTDOWN
                    IF _isinobject(msg.imsg.mousex,msg.imsg.mousey)
                        initx1:=data.x1
                        inity1:=data.y1
                        initx2:=data.x2
                        inity2:=data.y2
                        newx:=Div(Mul(msg.imsg.mousex-rx,1000),rw)
                        newy:=Div(Mul(msg.imsg.mousey-ry,1000),rh)

                        data.modB:=DR_COMPL
                        select:=1
                        IF Abs(newx-data.x1) < 20
                            zone:=1
                        ELSEIF Abs(newx-data.x2) < 20
                            zone:=3
                        ELSEIF _between(data.x1,newx,data.x2)
                            zone:=2
                        ELSE
                            zone:=0
                        ENDIF
                        IF Abs(newy-data.y2) < 20
                            zone:=zone*5
                        ELSEIF _between(data.y1,newy,data.y2)
                            zone:=zone*4
                        ELSEIF Abs(newy-data.y1) > 20
                            zone:=0
                        ENDIF
                        IF zone=0
                            data.ax1:=newx;data.ax2:=newx;data.ay1:=newy;data.ay2:=newy
                            data.bx1:=newx;data.bx2:=newx;data.by1:=newy;data.by2:=newy
                        ELSEIF zone=8
                            data.x1:=newx-data.x1      /*data.z1 contain the position of*/
                            data.y1:=newy-data.y1      /*the handle*/
                            data.x2:=data.x2-newx
                            data.y2:=data.y2-newy
                        ENDIF
                        Mui_RequestIDCMP(obj,IDCMP_MOUSEMOVE)
                        requested:=TRUE
                    ENDIF
                ELSEIF (msg.imsg.code=SELECTUP) AND (select=1)
                    select:=0
                    Mui_RejectIDCMP(obj,IDCMP_MOUSEMOVE)
                    requested:=FALSE
                    IF _isinobject(msg.imsg.mousex,msg.imsg.mousey)

                        newx:=Div(Mul(msg.imsg.mousex-rx,1000),rw)
                        newy:=Div(Mul(msg.imsg.mousey-ry,1000),rh)

                        SELECT zone
                        CASE 0 -> outside
                            data.ax1:=data.bx1;data.ay1:=data.by1
                            data.ax2:=data.bx2;data.ay2:=data.by2
                            data.modA:=DR_COMPL

                            IF (Abs(data.ax1-data.ax2) < 20) AND (Abs(data.ay1-data.ay2) < 20)
                                data.x1:=-1;data.x2:=-1
                                data.y1:=-1;data.y2:=-1
                            ELSE
                                data.bx2:=Div(Mul(msg.imsg.mousex-rx,1000),rw)
                                data.by2:=Div(Mul(msg.imsg.mousey-ry,1000),rh)
                                data.x1:=data.bx1
                                data.y1:=data.by1
                                data.x2:=data.bx2
                                data.y2:=data.by2

                                /*data.x1:=newx;data.y1:=newy
                                data.x2:=tx;data.y2:=ty */
                            ENDIF
                            Mui_Redraw(obj,MADF_DRAWUPDATE)
                        CASE 1 -> 7
                            data.ax1:=data.bx1;data.ay1:=data.by1
                            data.bx1:=newx
                            data.by1:=newy
                            data.x1:=newx
                            data.y1:=newy

                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=initx2-((initx2-optr.x)*(initx2-newx)/(initx2-initx1))
                                        optr.y:=inity2-((inity2-optr.y)*(inity2-newy)/(inity2-inity1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 2 -> 8
                            data.ay1:=data.by1
                            data.by1:=newy
                            data.y1:=newy
                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.y:=inity2-((inity2-optr.y)*(inity2-newy)/(inity2-inity1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 3 -> 9
                            data.ax2:=data.bx2;data.ay1:=data.by1
                            data.bx2:=newx
                            data.by1:=newy
                            data.x2:=newx
                            data.y1:=newy
                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=initx1+((optr.x-initx1)*(newx-initx1)/(initx2-initx1))
                                        optr.y:=inity2-((inity2-optr.y)*(inity2-newy)/(inity2-inity1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF

                        CASE 4 -> 4
                            data.ax1:=data.bx1
                            data.bx1:=newx
                            data.x1:=newx
                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=initx2-((initx2-optr.x)*(initx2-newx)/(initx2-initx1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 8 -> 5

                            /*data.ax1:=data.bx1;data.ay1:=data.by1
                            data.ax2:=data.bx2;data.ay2:=data.by2
                            data.modA:=DR_COMPL*/

                            data.bx1:=newx-data.x1
                            data.bx2:=newx+data.x2
                            data.by1:=newy-data.y1
                            data.by2:=newy+data.y2

                            data.x1:=data.bx1
                            data.x2:=data.bx2
                            data.y1:=data.by1
                            data.y2:=data.by2

                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=optr.x+(data.x1-initx1)
                                        optr.y:=optr.y+(data.y1-inity1)
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 12-> 6
                            data.ax2:=data.bx2
                            data.bx2:=newx
                            data.x2:=newx
                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=initx1+((optr.x-initx1)*(newx-initx1)/(initx2-initx1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 5 -> 1
                            data.ax1:=data.bx1;data.ay2:=data.by2
                            data.bx1:=newx
                            data.by2:=newy
                            data.x1:=newx
                            data.y2:=newy
                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=initx2-((initx2-optr.x)*(initx2-newx)/(initx2-initx1))
                                        optr.y:=inity1+((optr.y-inity1)*(newy-inity1)/(inity2-inity1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 10-> 2
                            data.ay2:=data.by2
                            data.by2:=newy
                            data.y2:=newy
                            IF data.temp = NIL
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.y:=inity1+((optr.y-inity1)*(newy-inity1)/(inity2-inity1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        CASE 15-> 3
                            data.ax2:=data.bx2;data.ay2:=data.by2
                            data.bx2:=newx
                            data.by2:=newy
                            data.x2:=newx
                            data.y2:=newy                /*the gap with (ix1;iy1)
                                                           must be multiplied by (iw;ih) and divided*/
                            IF data.temp = NIL           /*by (nw;nh)*/
                                FOR z:=0 TO nobjs-1
                                    optr:=objs[z]
                                    IF _between(initx1,optr.x,initx2) AND _between(inity1,optr.y,inity2)
                                        optr.x:=initx1+((optr.x-initx1)*(newx-initx1)/(initx2-initx1))
                                        optr.y:=inity1+((optr.y-inity1)*(newy-inity1)/(inity2-inity1))
                                        moved:=TRUE
                                    ENDIF
                                ENDFOR
                            ENDIF
                        ENDSELECT
                        data.modB:=DR_NORM
                        IF moved
                            relayout(obj)
                        ELSE
                            Mui_Redraw(obj,MADF_DRAWOBJECT)
                        ENDIF
                    ELSE
                        data.ax1:=data.bx1;data.ay1:=data.by1
                        data.ax2:=data.bx2;data.ay2:=data.by2
                        data.modA:=DR_COMPL
                    ENDIF
                ENDIF
            CASE IDCMP_MOUSEMOVE
                IF requested        -> We only work if the Boss asked it.
                    IF _isinobject(msg.imsg.mousex,msg.imsg.mousey)
                        newx:=Div(Mul(msg.imsg.mousex-rx,1000),rw)
                        newy:=Div(Mul(msg.imsg.mousey-ry,1000),rh)
                        SELECT zone
                        CASE 0
                            data.ax2:=data.bx2;data.ay2:=data.by2
                            data.bx2:=newx
                            data.by2:=newy
                        CASE 1
                            data.ax1:=data.bx1;data.ay1:=data.by1
                            data.bx1:=newx
                            data.by1:=newy
                        CASE 2
                            data.ay1:=data.by1
                            data.by1:=newy
                        CASE 3
                            data.ax2:=data.bx2;data.ay1:=data.by1
                            data.bx2:=newx
                            data.by1:=newy
                        CASE 4
                            data.ax1:=data.bx1
                            data.bx1:=newx
                        CASE 8
                            data.ax1:=data.bx1;data.ay1:=data.by1
                            data.ax2:=data.bx2;data.ay2:=data.by2
                            data.bx1:=newx-data.x1
                            data.bx2:=newx+data.x2
                            data.by1:=newy-data.y1
                            data.by2:=newy+data.y2
                        CASE 12
                            data.ax2:=data.bx2
                            data.bx2:=newx
                        CASE 5
                            data.ax1:=data.bx1;data.ay2:=data.by2
                            data.bx1:=newx
                            data.by2:=newy
                        CASE 10
                            data.ay2:=data.by2
                            data.by2:=newy
                        CASE 15
                            data.ax2:=data.bx2;data.ay2:=data.by2
                            data.bx2:=newx
                            data.by2:=newy
                        ENDSELECT
                        data.modA:=DR_COMPL
                        data.modB:=DR_COMPL
                        Mui_Redraw(obj,MADF_DRAWUPDATE)
                    ENDIF
                ENDIF
            ENDSELECT
        ENDIF
    ENDIF
ENDPROC 

PROC logic_c_dragquery(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_dragdrop)
    IF msg.obj=poppen
        RETURN MUIV_DragQuery_Refuse
    ELSEIF msg.obj=selpen
        RETURN MUIV_DragQuery_Refuse
    ENDIF
ENDPROC MUIV_DragQuery_Accept

PROC logic_c_draw(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_draw)
DEF j,k,optr:PTR TO objet,optr2:PTR TO objet,x1,x2,y1,y2,hei,wid2,hei2,mptr:PTR TO macro,mptr2:PTR TO macro,
data:PTR TO logic_c_data,dmod
    data:=INST_DATA(cl,obj)
    doSuperMethodA(cl,obj,msg) /*draw the frame and so on*/

    IF msg.flags AND (MADF_DRAWUPDATE OR MADF_DRAWOBJECT)

        IF data.wirechange
            data.wirechange:=FALSE
            Mui_ReleasePen(muiRenderInfo(obj),data.wire)
            data.wire:=Mui_ObtainPen(muiRenderInfo(obj),data.wirespec,0)
        ENDIF
        IF data.selcchange
            data.selcchange:=FALSE
            Mui_ReleasePen(muiRenderInfo(obj),data.selc)
            data.selc:=Mui_ObtainPen(muiRenderInfo(obj),data.selcspec,0)
        ENDIF

        IF (data.modA+data.modB=DR_NONE) AND (data.y2<>-1)
            SetAPen(_rp(obj),MUIPEN(data.selc))
            x1:= Min(_mwidth(obj),Div(Mul(data.x1,_mwidth(obj)),1000))+_mleft(obj)
            y1:= Min(_mheight(obj),Div(Mul(data.y1,_mheight(obj)),1000))+_mtop(obj)
            x2:= Min(_mwidth(obj),Div(Mul(data.x2,_mwidth(obj)),1000))+_mleft(obj)
            y2:= Min(_mheight(obj),Div(Mul(data.y2,_mheight(obj)),1000))+_mtop(obj)
            Move(_rp(obj),x1,y1)
            Draw(_rp(obj),x1,y2)
            Draw(_rp(obj),x2,y2)
            Draw(_rp(obj),x2,y1)
            Draw(_rp(obj),x1,y1)

            Move(_rp(obj),x1+1,y1+1)
            Draw(_rp(obj),x1+1,y2-1)
            Draw(_rp(obj),x2-1,y2-1)
            Draw(_rp(obj),x2-1,y1+1)
            Draw(_rp(obj),x1+1,y1+1)
        ENDIF

        dmod:=data.modA

        SELECT dmod
        CASE DR_COMPL
            SetDrMd(_rp(obj),RP_COMPLEMENT)
            x1:= Min(_mwidth(obj),Div(Mul(data.ax1,_mwidth(obj)),1000))+_mleft(obj)
            y1:= Min(_mheight(obj),Div(Mul(data.ay1,_mheight(obj)),1000))+_mtop(obj)
            x2:= Min(_mwidth(obj),Div(Mul(data.ax2,_mwidth(obj)),1000))+_mleft(obj)
            y2:= Min(_mheight(obj),Div(Mul(data.ay2,_mheight(obj)),1000))+_mtop(obj)
            Move(_rp(obj),x1,y1)
            Draw(_rp(obj),x1,y2)
            Draw(_rp(obj),x2,y2)
            Draw(_rp(obj),x2,y1)
            Draw(_rp(obj),x1,y1)
            SetDrMd(_rp(obj),RP_JAM1)
        CASE DR_NORM
            SetAPen(_rp(obj),MUIPEN(data.selc))
            x1:= Min(_mwidth(obj),Div(Mul(data.ax1,_mwidth(obj)),1000))+_mleft(obj)
            y1:= Min(_mheight(obj),Div(Mul(data.ay1,_mheight(obj)),1000))+_mtop(obj)
            x2:= Min(_mwidth(obj),Div(Mul(data.ax2,_mwidth(obj)),1000))+_mleft(obj)
            y2:= Min(_mheight(obj),Div(Mul(data.ay2,_mheight(obj)),1000))+_mtop(obj)
            Move(_rp(obj),x1,y1)
            Draw(_rp(obj),x1,y2)
            Draw(_rp(obj),x2,y2)
            Draw(_rp(obj),x2,y1)
            Draw(_rp(obj),x1,y1)

            Move(_rp(obj),x1+1,y1+1)
            Draw(_rp(obj),x1+1,y2-1)
            Draw(_rp(obj),x2-1,y2-1)
            Draw(_rp(obj),x2-1,y1+1)
            Draw(_rp(obj),x1+1,y1+1)
        ENDSELECT
        data.modA:=DR_NONE

        dmod:=data.modB
        SELECT dmod
        CASE DR_COMPL
            SetDrMd(_rp(obj),RP_COMPLEMENT)
            x1:= Min(_mwidth(obj),Div(Mul(data.bx1,_mwidth(obj)),1000))+_mleft(obj)
            y1:= Min(_mheight(obj),Div(Mul(data.by1,_mheight(obj)),1000))+_mtop(obj)
            x2:= Min(_mwidth(obj),Div(Mul(data.bx2,_mwidth(obj)),1000))+_mleft(obj)
            y2:= Min(_mheight(obj),Div(Mul(data.by2,_mheight(obj)),1000))+_mtop(obj)
            Move(_rp(obj),x1,y1)
            Draw(_rp(obj),x1,y2)
            Draw(_rp(obj),x2,y2)
            Draw(_rp(obj),x2,y1)
            Draw(_rp(obj),x1,y1)
            SetDrMd(_rp(obj),RP_JAM1)
        CASE DR_NORM
            SetAPen(_rp(obj),MUIPEN(data.selc))
            x1:= Min(_mwidth(obj),Div(Mul(data.bx1,_mwidth(obj)),1000))+_mleft(obj)
            y1:= Min(_mheight(obj),Div(Mul(data.by1,_mheight(obj)),1000))+_mtop(obj)
            x2:= Min(_mwidth(obj),Div(Mul(data.bx2,_mwidth(obj)),1000))+_mleft(obj)
            y2:= Min(_mheight(obj),Div(Mul(data.by2,_mheight(obj)),1000))+_mtop(obj)
            Move(_rp(obj),x1,y1)
            Draw(_rp(obj),x1,y2)
            Draw(_rp(obj),x2,y2)
            Draw(_rp(obj),x2,y1)
            Draw(_rp(obj),x1,y1)

            Move(_rp(obj),x1+1,y1+1)
            Draw(_rp(obj),x1+1,y2-1)
            Draw(_rp(obj),x2-1,y2-1)
            Draw(_rp(obj),x2-1,y1+1)
            Draw(_rp(obj),x1+1,y1+1)
        ENDSELECT
        data.modB:=DR_NONE

        IF data.temp = NIL
            FOR j:=0 TO data.nobjs-1
                optr:=data.objs[j]
                mptr:=optr.macro
                IF mptr.nin <> 0    /*draws the links*/
                    get(optr.gad,MUIA_Width,{wid2})
                    get(optr.gad,MUIA_Height,{hei2})

                    SetAPen(_rp(obj),MUIPEN(data.wire))

                    FOR k:=0 TO mptr.nin-1
                        IF optr.ins[k] <> NIL
                            optr2:=optr.ins[k]
                            mptr2:=optr2.macro
                            get(optr2.gad,MUIA_Height,{hei})
                            x1:= Min(_mwidth(obj), Div(Mul(optr2.x,_mwidth(obj) ),1000))+wid2+_mleft(obj)
                            y1:= Min(_mheight(obj),Div(Mul(optr2.y,_mheight(obj)),1000))+(hei2*(optr.ind[k]+1)/(mptr2.nout+1))+_mtop(obj)
                            x2:= Min(_mwidth(obj), Div(Mul(optr.x, _mwidth(obj) ),1000))+_mleft(obj)
                            y2:= Min(_mheight(obj),Div(Mul(optr.y, _mheight(obj)),1000))+(hei*(k+1)/(mptr.nin+1))+_mtop(obj)
                            Move(_rp(obj),x1,y1)
                            Draw(_rp(obj),x2,y2)
                            IF befat = MUI_TRUE
                                Move(_rp(obj),x1+1,y1)
                                Draw(_rp(obj),x2+1,y2)
                                Move(_rp(obj),x1,y1+1)
                                Draw(_rp(obj),x2,y2+1)
                            ENDIF
                        ENDIF
                    ENDFOR
                ENDIF
            ENDFOR
        ENDIF
    ENDIF
ENDPROC

PROC logic_c_dispatcher(cl:PTR TO iclass,obj,msg:PTR TO msg)
DEF methodid
    methodid:=msg.methodid
    SELECT methodid
        CASE OM_NEW          ; RETURN logic_c_new(cl,obj,msg)
        CASE OM_SET          ; RETURN logic_c_set(cl,obj,msg)
        CASE OM_GET          ; RETURN logic_c_get(cl,obj,msg)
        CASE MUIM_Setup      ; RETURN logic_c_setup(cl,obj,msg)
        CASE MUIM_Cleanup    ; RETURN logic_c_cleanup(cl,obj,msg)
        CASE MUIM_DragQuery  ; RETURN logic_c_dragquery(cl,obj,msg)
        CASE MUIM_DragDrop   ; RETURN logic_c_dragdrop(cl,obj,msg)
        CASE MUIM_Draw       ; RETURN logic_c_draw(cl,obj,msg)
        CASE MUIM_HandleInput; RETURN logic_c_handleinput(cl,obj,msg)
    ENDSELECT
ENDPROC (doSuperMethodA(cl,obj,msg))

/****************************** -> The first displayed element (i.e. wires button)
**  Pitem class              **    will manage necessary colours.
******************************/

OBJECT pitem_data
    dummy:CHAR -> No data needed for this simple class
ENDOBJECT

PROC pitem_dispatcher(cl:PTR TO iclass,obj,msg:PTR TO msg)
DEF methodid
    methodid:=msg.methodid
    SELECT methodid
        CASE MUIM_Setup      ; RETURN pitem_setup(cl,obj,msg)
        CASE MUIM_Cleanup    ; RETURN pitem_cleanup(cl,obj,msg)
    ENDSELECT
ENDPROC (doSuperMethodA(cl,obj,msg))

PROC pitem_setup(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
    FOR u:=0 TO 255
        StringF(pspec,'r\z\h[2]\z\h[2]\z\h[2]\z\h[2],\z\h[2]\z\h[2]\z\h[2]\z\h[2],\z\h[2]\z\h[2]\z\h[2]\z\h[2]\0\0\0\0',
        paltte[u*3],paltte[u*3],paltte[u*3],paltte[u*3],
        paltte[u*3+1],paltte[u*3+1],paltte[u*3+1],paltte[u*3+1],
        paltte[u*3+2],paltte[u*3+2],paltte[u*3+2],paltte[u*3+2])
        val:=Mui_ObtainPen(muiRenderInfo(obj),pspec,0)
        to_release[u]:=val
        mapping_table[u]:=MUIPEN(val)
    ENDFOR                                                  /* I've put the call to the supermethod at the end.*/
    IF doSuperMethodA(cl,obj,msg)=FALSE THEN RETURN FALSE   /* This is ILLEGAL but I did not see*/
ENDPROC MUI_TRUE                                            /* any other way to allocate the colours*/
                                                            /* before any setup and after the screen's*/
                                                            /* ready.*/
PROC pitem_cleanup(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
    IF doSuperMethodA(cl,obj,msg)=FALSE THEN RETURN FALSE
    FOR u:=0 TO 255
        Mui_ReleasePen(muiRenderInfo(obj),to_release[u])
    ENDFOR
ENDPROC MUI_TRUE

/*********************
** Hook functions   **
*********************/

PROC delFunc(group,st)   /*I'm forced to put at least one argument. Here is st (useless).*/
DEF data:PTR TO logic_c_data,z,optr:PTR TO objet
    data:=INST_DATA(cl_logic_c.mcc_class,group)
    IF data.temp = NIL
        FOR z:=0 TO data.nobjs-1
            optr:=data.objs[z]
            IF (optr.x>data.x1) AND (optr.x<data.x2) AND (optr.y>data.y1) AND (optr.y<data.y2)
                deleteobj(optr,data)
                z--
            ENDIF
        ENDFOR
    ENDIF
    fullcalc(data)
ENDPROC
PROC deleteobj(optr:PTR TO objet,data:PTR TO logic_c_data)
DEF temp,z,optr2:PTR TO objet,k,mptr:PTR TO macro,group,f,gg

    get(optr.gad,MUIA_Parent,{gg})
    get(gg,MUIA_Parent,{group})
    doMethodA(group,[MUIM_Group_InitChange])
    FOR z:=0 TO data.nobjs-1
        optr2:=data.objs[z]
        mptr:=optr2.macro
        FOR k:=0 TO mptr.nin
            IF optr2.ins[k] = optr THEN optr2.ins[k]:=NIL
        ENDFOR
    ENDFOR
    IF data.nobjs=1
        temp:=RectangleObject,End
        doMethodA(group,[OM_ADDMEMBER,temp])
        data.temp:=temp
    ENDIF
    data.nobjs:=data.nobjs-1
    get(optr.gad,MUIA_Parent,{gg})
    doMethodA(group,[OM_REMMEMBER,gg])
    mptr:=optr.macro
    END optr.ins[mptr.nin]
    END optr.ind[mptr.nin]
    f:=optr
    END optr
    IF data.temp <> NIL
        END data.objs
    ELSE
        t:=data.objs
        NEW data.objs[data.nobjs]
        k:=0
        FOR z:=0 TO data.nobjs-1
            IF t[z]=f THEN k++
            data.objs[z]:=t[z+k]
        ENDFOR
    ENDIF
    doMethodA(group,[MUIM_Group_ExitChange])
    IF data.temp <> NIL THEN relayout(group)
ENDPROC

PROC layoutFunc(h:PTR TO hook,obj:PTR TO object,lm:PTR TO mui_layoutmsg)
DEF optr:PTR TO objet,type,cstate:PTR TO object,child:PTR TO object,
      mw,mh,l,t,j,dolr=TRUE,data:PTR TO logic_c_data
  data:=INST_DATA(cl_logic_c.mcc_class,obj)
  type:=lm.lm_type
  SELECT type
    CASE MUILM_MINMAX
      /*doSuperMethodA(cl,obj,msg)*/
      lm.lm_minmax.minwidth  := /*lm.lm_minmax.minwidth+*/100
      lm.lm_minmax.minheight := /*lm.lm_minmax.minheight+*/100
      lm.lm_minmax.defwidth  := /*lm.lm_minmax.defwidth+*/200
      lm.lm_minmax.defheight := /*lm.lm_minmax.defheight+*/200
      lm.lm_minmax.maxwidth  := MUI_MAXMAX
      lm.lm_minmax.maxheight := MUI_MAXMAX
      RETURN (0)

    CASE MUILM_LAYOUT
      cstate := lm.lm_children.head
      j:=-1
      WHILE (child := NextObject({cstate}))
        mw := _minwidth(child)
        mh := _minheight(child)
        IF data.temp <> NIL
            l:=5;t:=5
        ELSE
            optr:=data.objs[]
            IF dolr
                l:=10
                t:=10
                mw:=10;mh:=10
                dolr:=FALSE
            ELSE
                j:=j+1
                optr:=data.objs[j]
                l  := Min(lm.lm_layout.width -mw,Div(Mul(optr.x,lm.lm_layout.width ),1000))
                t  := Min(lm.lm_layout.height-mh,Div(Mul(optr.y,lm.lm_layout.height),1000))
            ENDIF
        ENDIF
        IF (Mui_Layout(child,l,t,mw,mh,0))=NIL THEN RETURN (FALSE)
      ENDWHILE
      RETURN (MUI_TRUE)
  ENDSELECT
ENDPROC (MUILM_UNKNOWN)

PROC logic_c_dragdrop(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_dragdrop)
DEF optr:PTR TO objet,rw,rh,rx,ry,error,z,mptr:PTR TO macro,j
DEF data:PTR TO logic_c_data,window,bmp:PTR TO bitmap,firsto,gg
    data:=INST_DATA(cl,obj)
    data.changed:=TRUE
    firsto:=(data.temp<>NIL)
    window:=data.window
    get(obj,MUIA_Width,{rw})
    get(window,MUIA_Window_LeftEdge,{z})
    get(obj,MUIA_LeftEdge,{rx})
    rx:=rx+z
    get(obj,MUIA_Height,{rh})
    get(window,MUIA_Window_TopEdge,{z})
    get(obj,MUIA_TopEdge,{ry})
    ry:=ry+z
    optr:=findobj(msg.obj,data)
    IF optr=NIL    ->Creation
        IF firsto
            NEW data.objs[1]
            NEW optr
            data.objs[]:=optr
        ELSE
            t:=data.objs
            NEW data.objs[data.nobjs+1]
            NEW optr
            FOR j:=0 TO data.nobjs-1
                data.objs[j]:=t[j]
            ENDFOR
            data.objs[data.nobjs]:=optr
        ENDIF

        optr.x:=Div(Mul(msg.x-rx,1000),rw)
        optr.y:=Div(Mul(msg.y-ry,1000),rh)
        FOR j:=0 TO nmacros
            error:=FALSE
            mptr:=macros[j]
            EXIT msg.obj=mptr.gad
            error:=TRUE
        ENDFOR
        IF error
            WriteF('Where did you find that gadget?\nIt isn''t on any list!\n')
        ELSE
            optr.macro:=mptr
            NEW optr.ins[mptr.nin]
            NEW optr.ind[mptr.nin]

            FOR j:=0 TO mptr.nin-1
                optr.ins[j]:=NIL
            ENDFOR
            pic:=mptr.pictures[]
            bmp:=pic.bitmap()
            optr.gad:=case(bmp)
            gg:=VGroup,
                    Child,optr.gad,
                End

            IF optr.gad <> NIL
                IF doMethodA(obj,[MUIM_Group_InitChange]) = NIL
                    Raise('MUIM_Group_InitChange returned NIL!')
                ENDIF
                IF firsto
                    doMethodA(obj,[OM_REMMEMBER,data.temp])
                ENDIF
                doMethodA(obj,[OM_ADDMEMBER,gg])
                doMethodA(obj,[MUIM_Group_ExitChange])
                doMethodA(optr.gad,[MUIM_Notify,MUIA_Selected,MUIV_EveryTime,app,3,MUIM_WriteLong,FALSE,{background}])
                doMethodA(optr.gad,[MUIM_Notify,MUIA_Pressed,FALSE,app,3,MUIM_CallHook,pressHook,optr])
                IF firsto
                    data.nobjs:=1
                    data.temp:=NIL
                ELSE
                    data.nobjs:=data.nobjs+1
                ENDIF
            ELSE
                Mui_RequestA(app,window,0,'Object creation',NIL,'Couldn''t create an object!',NIL)
            ENDIF
            IF firsto THEN relayout(obj)
        ENDIF
    ELSE    ->Move
        optr.x:=Div(Mul(msg.x-rx,1000),rw)
        optr.y:=Div(Mul(msg.y-ry,1000),rh)
        relayout(obj)
    ENDIF
ENDPROC

PROC pressFunc(app:PTR TO object,aa:PTR TO LONG)
DEF optr:PTR TO objet,mptr:PTR TO macro,intwin,rely,gadheight,o,j,grp,
data:PTR TO logic_c_data,bmp:PTR TO bitmap,gg,window

    background:=FALSE

    optr:=aa[]
    get(optr.gad,MUIA_Parent,{gg})
    get(gg,MUIA_Parent,{grp})           -> group
    data:=INST_DATA(cl_logic_c.mcc_class,grp)
    window:=data.window
    get(window,MUIA_Window_Window,{intwin}) -> intuition window

    mptr:= optr.macro
    SELECT mode
    CASE MD_NONE
        IF mptr.inOM
            optr.state:=Not(optr.state)
            o:=0
            IF (mptr.outOM=TRUE) AND (optr.value AND 1)
                o:=2
            ENDIF
            IF optr.state THEN o++
            pic:=mptr.pictures[o]
            bmp:=pic.bitmap()
            setbitmap(optr.gad,bmp)
            fullcalc(data)
            data.changed:=TRUE
        ENDIF
    CASE MD_BEGIN
        IF mptr.outOM
            o:=mptr.nout-1
        ELSE
            o:=mptr.nout
        ENDIF
        IF o > 0
            sourceg:=grp
            source:=optr
            get(optr.gad,MUIA_TopEdge,{rely}) -> rely = position of the gadget relative to the top of the window.
            get(optr.gad,MUIA_Height,{gadheight})
            rely:=MouseY(intwin)-rely         -> rely = position of the pointer relative to the top of the gadget.
            sourced:=rely/(gadheight/o)
            mode:=MD_FINISH
        ELSE
            bip()
        ENDIF
    CASE MD_FINISH
        IF mptr.inOM
            o:=mptr.nin-1
        ELSE
            o:=mptr.nin
        ENDIF  
        IF (o > 0) AND (sourceg=grp)
            get(optr.gad,MUIA_TopEdge,{rely})
            get(optr.gad,MUIA_Height,{gadheight})
            rely:=MouseY(intwin)-rely
            rely:=rely/(gadheight/o)
            IF optr.ins[rely] = NIL
                o:=MADF_DRAWUPDATE
            ELSE
                o:=MADF_DRAWOBJECT
            ENDIF
            optr.ins[rely]:=source
            optr.ind[rely]:=sourced
            mode:=MD_NONE
            fullcalc(data)
            Mui_Redraw(grp,o)
            data.changed:=TRUE
        ELSE
            bip()
        ENDIF
    CASE MD_IN
        FOR j:=0 TO nmNin-1
            IF nmIn[j]=optr
                nmNin--
                FOR o:=j TO nmNin-1
                    nmIn[o]:=nmIn[o+1]
                ENDFOR
                RETURN
            ENDIF
        ENDFOR
        IF nmNin=10
            bip()
        ELSE
            nmIn[nmNin++]:=optr
        ENDIF
    CASE MD_INA
        IF nmIna=optr
            nmIna:=NIL
        ELSE
            nmIna:=optr
        ENDIF
        mode:=MD_NONE
    CASE MD_OUT
        FOR j:=0 TO nmNout-1
            IF nmOut[j]=optr
                nmNout--
                FOR o:=j TO nmNout-1
                    nmOut[o]:=nmOut[o+1]
                ENDFOR
                RETURN
            ENDIF
        ENDFOR
        IF nmNout=10
            bip()
        ELSE
            nmOut[nmNout++]:=optr
        ENDIF
    CASE MD_OUTA
        IF nmOuta=optr
            nmOuta:=NIL
        ELSE
            nmOuta:=optr
        ENDIF
        mode:=MD_NONE
    ENDSELECT
ENDPROC

PROC exitclasses()
    IF (cl_logic_c) THEN Mui_DeleteCustomClass(cl_logic_c)
    IF (cl_pitem) THEN Mui_DeleteCustomClass(cl_pitem)
ENDPROC

PROC initclasses()
    IF (cl_logic_c := eMui_CreateCustomClass(NIL,MUIC_Group ,NIL,SIZEOF logic_c_data,{logic_c_dispatcher})) AND
       (cl_pitem := eMui_CreateCustomClass(NIL,MUIC_Bitmap ,NIL,SIZEOF pitem_data,{pitem_dispatcher}))
        initialized:=TRUE
        RETURN TRUE
    ELSE
        exitclasses()
        initialized:=FALSE
        RETURN FALSE
    ENDIF
ENDPROC

PROC main() HANDLE
DEF bmp:PTR TO bitmap
    systgads[0]:=loadspic('images/in');systbmps[0]:=pic.bitmap()
    systgads[1]:=loadspic('images/inA');systbmps[1]:=pic.bitmap()
    systgads[2]:=loadspic('images/out');systbmps[2]:=pic.bitmap()
    systgads[3]:=loadspic('images/outA');systbmps[3]:=pic.bitmap()
    systgads[4]:=loadspic('images/Save');systbmps[4]:=pic.bitmap()
    systgads[5]:=loadspic('images/Fils');systbmps[5]:=pic.bitmap()
    systgads[6]:=loadspic('images/Load');systbmps[6]:=pic.bitmap()
    systgads[7]:=loadspic('images/NewWin');systbmps[7]:=pic.bitmap()
    systgads[8]:=loadspic('images/Prefs');systbmps[8]:=pic.bitmap()
    FOR u:=0 TO 3
        files[u]:=String(60)
    ENDFOR
    /*pal:=pic.palette()
    r,g,b:=pal.getRGB(0)
    WriteF('paltte:=[\d,\d,\d,\n',r,g,b)
    FOR u:=1 TO 255
        r,g,b:=pal.getRGB(u)
        WriteF('\h,\h,\h\n',r,g,b)
    ENDFOR
    WriteF(']\n') */
              /*It would be better to read from the file :-) But how? */
    paltte:= [$00,$00,$00,$FF,$FF,$FF,$EE,$EE,$EE,$DD,$DD,$DD,
              $CC,$CC,$CC,$BB,$BB,$BB,$AA,$AA,$AA,$99,$99,$99,
              $88,$88,$88,$77,$77,$77,$66,$66,$66,$55,$55,$55,
              $44,$44,$44,$33,$33,$33,$22,$22,$22,$11,$11,$11,
              $00,$55,$44,$00,$88,$99,$00,$BB,$99,$33,$22,$00,
              $44,$33,$00,$66,$44,$11,$77,$55,$22,$99,$66,$33,
              $BB,$77,$55,$CC,$99,$77,$EE,$AA,$99,$FF,$CC,$AA,
              $FF,$CC,$BB,$CC,$88,$88,$EE,$88,$CC,$77,$00,$44,
              $FF,$00,$00,$FF,$22,$00,$FF,$55,$00,$FF,$77,$00,
              $FF,$AA,$00,$FF,$DD,$00,$FF,$FF,$00,$DD,$FF,$00,
              $AA,$FF,$00,$88,$FF,$00,$55,$FF,$00,$22,$FF,$00,
              $00,$FF,$00,$00,$FF,$33,$00,$FF,$77,$00,$FF,$BB,
              $00,$FF,$FF,$00,$CC,$FF,$00,$88,$FF,$00,$44,$FF,
              $00,$00,$FF,$22,$00,$FF,$55,$00,$FF,$77,$00,$FF,
              $AA,$00,$FF,$DD,$00,$FF,$FF,$00,$FF,$FF,$00,$DD,
              $FF,$00,$AA,$FF,$00,$88,$FF,$00,$55,$FF,$00,$33,
    /*64th*/  $FF,$AA,$AA,$FF,$BB,$AA,$FF,$CC,$AA,$FF,$DD,$AA,
              $FF,$EE,$AA,$FF,$FF,$AA,$FF,$FF,$AA,$FF,$FF,$AA,
              $EE,$FF,$AA,$DD,$FF,$AA,$CC,$FF,$AA,$BB,$FF,$AA,
              $AA,$FF,$AA,$AA,$FF,$BB,$AA,$FF,$CC,$AA,$FF,$EE,
              $AA,$FF,$FF,$AA,$EE,$FF,$AA,$DD,$FF,$AA,$CC,$FF,
              $AA,$AA,$FF,$BB,$AA,$FF,$CC,$AA,$FF,$DD,$AA,$FF,
              $EE,$AA,$FF,$FF,$AA,$FF,$FF,$AA,$FF,$FF,$AA,$FF,
              $FF,$AA,$EE,$FF,$AA,$DD,$FF,$AA,$CC,$FF,$AA,$BB,
              $FF,$55,$55,$FF,$66,$55,$FF,$88,$55,$FF,$AA,$55,
              $FF,$CC,$55,$FF,$EE,$55,$FF,$FF,$55,$EE,$FF,$55,
              $CC,$FF,$55,$AA,$FF,$55,$88,$FF,$55,$66,$FF,$55,
              $55,$FF,$55,$55,$FF,$77,$55,$FF,$88,$55,$FF,$DD,
              $55,$FF,$FF,$55,$DD,$FF,$55,$AA,$FF,$55,$88,$FF,
              $55,$55,$FF,$66,$55,$FF,$88,$55,$FF,$AA,$55,$FF,
              $CC,$55,$FF,$EE,$55,$FF,$FF,$55,$FF,$FF,$55,$EE,
              $FF,$55,$CC,$FF,$55,$AA,$FF,$55,$88,$FF,$55,$77,
    /*128th*/ $CC,$00,$00,$CC,$11,$00,$CC,$44,$00,$CC,$55,$00,
              $CC,$88,$00,$CC,$BB,$00,$CC,$CC,$00,$BB,$CC,$00,
              $88,$CC,$00,$66,$CC,$00,$44,$CC,$00,$11,$CC,$00,
              $00,$CC,$00,$00,$CC,$22,$00,$CC,$55,$00,$CC,$99,
              $00,$CC,$CC,$00,$AA,$CC,$00,$66,$CC,$00,$33,$CC,
              $00,$00,$CC,$11,$00,$CC,$44,$00,$CC,$55,$00,$CC,
              $88,$00,$CC,$BB,$00,$CC,$CC,$00,$CC,$CC,$00,$BB,
              $CC,$00,$88,$CC,$00,$66,$CC,$00,$44,$CC,$00,$22,
              $99,$00,$00,$99,$11,$00,$99,$33,$00,$99,$44,$00,
              $99,$88,$00,$99,$66,$00,$99,$99,$00,$88,$99,$00,
              $66,$99,$00,$55,$99,$00,$33,$99,$00,$11,$99,$00,
              $00,$98,$00,$00,$99,$11,$00,$99,$44,$00,$99,$77,
              $00,$99,$99,$00,$77,$99,$00,$55,$99,$00,$22,$99,
              $00,$00,$99,$11,$00,$99,$33,$00,$99,$44,$00,$99,
              $66,$00,$99,$88,$00,$99,$99,$00,$99,$99,$00,$88,
              $99,$00,$66,$99,$00,$55,$99,$00,$33,$99,$00,$11,
    /*192nd*/ $66,$00,$00,$66,$11,$00,$66,$22,$00,$66,$33,$00,
              $66,$44,$00,$66,$55,$00,$66,$66,$00,$55,$66,$00,
              $44,$66,$00,$33,$66,$00,$22,$66,$00,$11,$66,$00,
              $00,$66,$00,$00,$66,$11,$00,$66,$22,$00,$66,$44,
              $00,$66,$66,$00,$55,$66,$00,$33,$66,$00,$11,$66,
              $00,$00,$66,$11,$00,$66,$22,$00,$66,$33,$00,$66,
              $44,$00,$66,$55,$00,$66,$66,$00,$66,$66,$00,$55,
              $66,$00,$44,$66,$00,$33,$66,$00,$22,$66,$00,$11,
              $33,$00,$00,$33,$00,$00,$33,$11,$00,$33,$11,$00,
              $33,$22,$00,$33,$22,$00,$33,$33,$00,$33,$33,$00,
              $22,$33,$00,$11,$33,$00,$11,$33,$00,$00,$33,$00,
              $00,$33,$00,$00,$33,$00,$00,$33,$11,$00,$33,$22,
              $00,$33,$33,$00,$22,$33,$00,$11,$33,$00,$00,$33,
              $00,$00,$33,$00,$00,$33,$11,$00,$33,$11,$00,$33,
              $22,$00,$33,$22,$00,$33,$33,$00,$33,$33,$00,$33,
              $33,$00,$22,$33,$00,$11,$33,$00,$11,$33,$00,$00,
   /*256th*/  NIL]

    screent:='Circuit 1.2'
    muimasterbase:=OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN)
    IF muimasterbase = NIL
        Raise('Couldn''t open muimaster.library!')
    ENDIF
    IF (utilitybase:=OpenLibrary('utility.library',36))=NIL THEN
        Raise('Failed to open utility.library') /*for tag-lists*/
    IF (aslbase:=OpenLibrary('asl.library',37))=NIL THEN
        Raise('Couldn''t open asl.library!')
    IF initclasses() = NIL
        Raise('Failed to init classes')
    ENDIF
    installhook(layoutHook,{layoutFunc});installhook(pressHook,{pressFunc});installhook(closeHook,{closeFunc});installhook(delHook,{delFunc})
    app:=ApplicationObject,
        MUIA_Application_Title, 'Circuit',
        MUIA_Application_Version,'$VER: Circuit 1.2 (07/04/98)',
        MUIA_Application_Author, 'Maxime Gamboni',
        MUIA_Application_Description, 'Logic Circuit Simulator',
        MUIA_Application_Base,'LCS',

        SubWindow, prefswin:=WindowObject,
            MUIA_Window_Title,'Circuit preferences',
            MUIA_Window_ScreenTitle,screent,
            MUIA_Window_ID,"LSCP",
            WindowContents,VGroup,
                Child, HGroup,
                    Child, poppen:=PoppenObject,MUIA_Window_Title,'Colour of wires',End,
                    Child, FreeLabel('Colour of wires'),
                End,
                Child, HGroup,
                    Child, selpen:=PoppenObject,MUIA_Window_Title,'Colour of selection',End,
                    Child, FreeLabel('Colour of selection'),
                End,
                Child, HGroup,
                    Child, fatwires:=CheckMark(FALSE),
                    Child, FreeLabel('Fat Wires?'),
                    Child, RectangleObject,End,
                End,
            End,
        End,

        SubWindow, waitwindow:=WindowObject,
            MUIA_Window_ScreenTitle,screent,
            MUIA_Window_ID,"WAIT",
            MUIA_Window_SizeGadget,FALSE,
            MUIA_Window_Width,MUIV_Window_Width_Screen(30),
            MUIA_Window_TopEdge,9999,
            WindowContents,VGroup,
                Child, wgauge:=GaugeObject,
                    GaugeFrame,
                    MUIA_Gauge_Max,100,
                    MUIA_Gauge_Horiz,MUI_TRUE,
                    End,
                Child,         ScaleObject,End,
                Child, wtext:= TextObject,TextFrame,End,
            End,
        End,

        SubWindow, toolswin:=WindowObject,          /*TOOLS WINDOW*/
            MUIA_Window_Title, 'Tools',
            MUIA_Window_ScreenTitle, screent,
            MUIA_Window_ID, "LSCT",
            MUIA_Window_Width, MUIV_Window_Width_Screen(50),
            MUIA_Window_Height, MUIV_Window_Height_Screen(50),
            WindowContents, HGroup,
                Child, ScrollgroupObject,
                    GroupFrameT('Circuit'),
                    MUIA_Scrollgroup_FreeHoriz,FALSE,
                    MUIA_Scrollgroup_HorizBar,NIL,
                    MUIA_Scrollgroup_Contents, VGroupV,
                        Child, bind:=NewObjectA(cl_pitem.mcc_class,NIL,
                           [ButtonFrame,
                            MUIA_FixWidth,27,
                            MUIA_FixHeight,27,
                            MUIA_Bitmap_Bitmap,systbmps[5],        /*sa palette est fausse!*/
                            MUIA_Bitmap_Width,27,
                            MUIA_Bitmap_Height,27,
                            MUIA_InputMode,MUIV_InputMode_RelVerify,
                            MUIA_Bitmap_MappingTable,mapping_table,
                        End,
                        Child, load :=button(systbmps[6]),
                        Child, save :=button(systbmps[4]),
                        Child,newwin:=button(systbmps[7]),

                        Child, prefs:= BitmapObject,ButtonFrame,
                            MUIA_InputMode,MUIV_InputMode_Toggle,
                            MUIA_FixWidth,27,
                            MUIA_FixHeight,27,
                            MUIA_Bitmap_Bitmap,systbmps[8],
                            MUIA_Bitmap_Width,27,
                            MUIA_Bitmap_Height,27,
                            MUIA_Bitmap_MappingTable,mapping_table,
                        End,
                        Child, RectangleObject,End,
                    End,
                End,
                Child, ScrollgroupObject,
                    GroupFrameT('List'),
                    MUIA_Scrollgroup_FreeHoriz,FALSE,
                    MUIA_Scrollgroup_HorizBar,NIL,
                    MUIA_Scrollgroup_Contents, macrolist:=VGroupV,End,
                End,
                Child, ScrollgroupObject,
                    GroupFrameT('Macro'),
                    MUIA_Scrollgroup_FreeHoriz,FALSE,
                    MUIA_Scrollgroup_HorizBar,NIL,
                    MUIA_Scrollgroup_Contents, VGroupV,
                        Child, mcrin:=button(systbmps[0]),
                        Child, mcrinA:=button(systbmps[1]),
                        Child, mcrout:=button(systbmps[2]),
                        Child, mcroutA:=button(systbmps[3]),
                        Child, mcrsave:=button(systbmps[4]),
                        Child, RectangleObject,End,
                    End,
                End,
            End,
        End,
    End
    IF app = NIL
        Raise('Couldn''t create application object!\n')
    ENDIF

    set(waitwindow,MUIA_Window_Title,'Initializing')
    set(waitwindow,MUIA_Window_Open,MUI_TRUE)
    set(wtext,MUIA_Text_Contents,'Opening project window')
    openwindow()
    set(wgauge,MUIA_Gauge_Current,33)
    set(wtext,MUIA_Text_Contents,'Loading macros')

    readmacros()
    set(wgauge,MUIA_Gauge_Current,67)
    set(wtext,MUIA_Text_Contents,'Opening Tools window')

    doMethodA(toolswin,[MUIM_Notify,MUIA_Window_CloseRequest,MUI_TRUE,      app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit])
    doMethodA(mcrin,   [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_MCRIN])
    doMethodA(mcrinA,  [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_MCRINA])
    doMethodA(mcrout,  [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_MCROUT])
    doMethodA(mcroutA, [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_MCROUTA])
    doMethodA(mcrsave, [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_MCRSAVE])
    doMethodA(bind,    [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_BIND])
    doMethodA(toolswin,[MUIM_Notify,MUIA_Window_InputEvent,  '-repeat space',app,2,MUIM_Application_ReturnID,ID_BIND])
    doMethodA(newwin,  [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_NEWWIN])
    doMethodA(load,    [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_LOAD])
    doMethodA(save,    [MUIM_Notify,MUIA_Pressed,            FALSE,         app,2,MUIM_Application_ReturnID,ID_SAVE])
    doMethodA(prefs,   [MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,prefswin,3,MUIM_NoNotifySet,MUIA_Window_Open,MUIV_TriggerValue])
    doMethodA(prefswin,[MUIM_Notify,MUIA_Window_CloseRequest,MUI_TRUE,      app,2,MUIM_Application_ReturnID,ID_CLOSEP])
    doMethodA(fatwires,[MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,app,3,MUIM_WriteLong,MUIV_TriggerValue,{befat}])

    set(toolswin,MUIA_Window_Open,MUI_TRUE)

    set(wgauge,MUIA_Gauge_Current,100)

    set(waitwindow,MUIA_Window_Open,FALSE)

    running:=TRUE

    WHILE running
        result:= doMethod(app, [MUIM_Application_Input,{sigs} ])
        SELECT result
        CASE MUIV_Application_ReturnID_Quit
            running:=FALSE
        CASE ID_BIND
            mode:=MD_BEGIN
        CASE ID_NEWWIN
            openwindow()
        CASE ID_CLOSEP
            set(prefswin,MUIA_Window_Open,FALSE)
            nnset(prefs,MUIA_Selected,FALSE)
        CASE ID_MCRIN
            mode:=MD_IN
        CASE ID_MCRINA
            mode:=MD_INA
        CASE ID_MCROUT
            mode:=MD_OUT
        CASE ID_MCROUTA
            mode:=MD_OUTA
        CASE ID_MCRSAVE
            StringF(s,'The new macro will contain \d ins\n' +
                      'and \d outs; inOM=\d and outOM=\d\n' +
                      'Is that correct?',nmNin+Sign(nmIna),nmNout+Sign(nmOuta),Sign(nmIna),Sign(nmOuta))
            IF Mui_RequestA(app,cwindow,0,'Create Macro','*_Yes|_No',s,NIL)=1
                NEW nmMacro
                nmMacro.nin:=nmNin+Sign(nmIna)
                nmMacro.nout:=nmNout+Sign(nmOuta)
                nmMacro.inOM:=(nmIna <> NIL)
                nmMacro.outOM:=(nmOuta <> NIL)
                IF loadreq('Default picture') = FALSE
                    END nmMacro
                    JUMP loop
                ENDIF
                nmMacro.pictures[]:=loadspic(s)
                StrCopy(files[],s)
                IF nmIna <> NIL
                    IF loadreq('Selected picture') = FALSE
                        END nmMacro
                        JUMP loop
                    ENDIF
                    nmMacro.pictures[1]:=loadspic(s)
                    StrCopy(files[1],s)
                ENDIF
                IF nmOuta <> NIL
                    IF loadreq('Lit picture') = FALSE
                        END nmMacro
                        JUMP loop
                    ENDIF
                    nmMacro.pictures[2]:=loadspic(s)
                    StrCopy(files[2],s)
                ENDIF
                IF (nmIna <> NIL) AND (nmOuta <> NIL)
                    IF loadreq('Selected and lit picture') = FALSE
                        END nmMacro
                        JUMP loop
                    ENDIF
                    nmMacro.pictures[3]:=loadspic(s)
                    StrCopy(files[3],s)
                ENDIF
                pic:=nmMacro.pictures[]
                bmp:=pic.bitmap()
                nmMacro.gad:=MUIimage(bmp)
                IF nmMacro.gad
                    doMethodA(macrolist,[MUIM_Group_InitChange])
                    doMethodA(macrolist,[OM_REMMEMBER,rectangle])
                    doMethodA(macrolist,[OM_ADDMEMBER,nmMacro.gad])
                    rectangle:=RectangleObject,End
                    doMethodA(macrolist,[OM_ADDMEMBER,rectangle])
                    doMethodA(macrolist,[MUIM_Group_ExitChange])
                ELSE
                    WriteF('Couldn''t create macro list!!!!!\n')
                ENDIF
                NEW nmMacro.values[powertwo(nmMacro.nin)]
                nmNin:=0 /*Now means the number of the next value*/
                get(cwindow,MUIA_Window_RootObject,{tgad})
                tdt:=INST_DATA(cl_logic_c.mcc_class,tgad)
                calcmacro(tdt,0,FALSE)
                calcmacro(tdt,0,TRUE)

                IF savereq('Save macro')
                    writemacro(s,nmMacro,files[],files[1],files[2],files[3])
                ENDIF

                addmacro(nmMacro) /*add to the macros[] array*/
                nmNin:=0
                nmNout:=0
                nmIna:=NIL
                nmOuta:=NIL
            ENDIF
        CASE ID_LOAD
            IF loadreq('Load circuit','Open','Circuits/')
                readcircuit(s)
            ENDIF
        CASE ID_SAVE
            get(cwindow,MUIA_Window_RootObject,{tgad})
            tdt:=INST_DATA(cl_logic_c.mcc_class,tgad)
            IF savereq('Save circuit','Circuits/')
                writecircuit(s,tdt,cwindow)
                set(cwindow,MUIA_Window_Title,FilePart(s))
            ENDIF
        ENDSELECT
loop:
        IF sigs THEN Wait(sigs)
    ENDWHILE
EXCEPT DO
    FOR u:=0 TO 255
        Mui_ReleasePen(muiRenderInfo(load),to_release[u])
    ENDFOR

    report_exception()
    FOR u:=0 TO 8
        IF systgads[u]
            pic:=systgads[u]
            END pic
        ENDIF
    ENDFOR
    ->IF pal THEN END pal
    IF dl THEN END dl
    IF app THEN Mui_DisposeObject(app)
    IF initialized THEN exitclasses()
    IF utilitybase THEN CloseLibrary(utilitybase)
    IF muimasterbase THEN CloseLibrary(muimasterbase)
    IF exception THEN WriteF('Program brutally interupted!\nInvoked reason:\n\s\n',exception)
ENDPROC

PROC doMethod( obj:PTR TO object, msg: PTR TO msg ) /* Written by Wouter van Oortmerssen */
DEF h:PTR TO hook, o:PTR TO object, dispatcher
    IF obj
        o:=obj-SIZEOF object
        h:= o.class
        dispatcher := h.entry
        MOVEA.L h,A0
        MOVEA.L msg,A1
        MOVEA.L obj,A2
        MOVEA.L dispatcher, A3
        JSR (A3)
        MOVE.L D0,o
        RETURN o
    ENDIF
ENDPROC NIL

PROC bip()
DEF scr
    get(toolswin,MUIA_Window_Screen,{scr});DisplayBeep(scr)
ENDPROC

PROC loadspic(path) ->load super_picture()
    NEW pic.super_picture(TRUE)
    pic.load(path)
ENDPROC pic

PROC openwindow()
DEF window,grp,temp,data:PTR TO logic_c_data,layoutr

    window:=WindowObject,
        MUIA_Window_Title, screent,
        MUIA_Window_ScreenTitle, screent,
        MUIA_Window_Width, MUIV_Window_Width_Screen(50),
        MUIA_Window_Height, MUIV_Window_Height_Screen(50),
        MUIA_Window_ID,nextid++,

        WindowContents, grp:=NewObjectA(cl_logic_c.mcc_class,NIL,
            [VirtualFrame,
                MUIA_Group_LayoutHook,layoutHook,
            End,
        End

    data:=INST_DATA(cl_logic_c.mcc_class,grp)
    temp:=RectangleObject,End
    layoutr:=RectangleObject,End
    doMethodA(grp,[OM_ADDMEMBER,temp])
    doMethodA(grp,[OM_ADDMEMBER,layoutr])
    data.objs:=NIL
    data.nobjs:=0
    data.temp:=temp
    data.changed:=FALSE
    data.layoutr:=layoutr
    data.window:=window
    doMethodA(app,[OM_ADDMEMBER,window])
    doMethodA(poppen,[MUIM_Notify,MUIA_Pendisplay_Spec,MUIV_EveryTime,grp,3,MUIM_Set,ATTR_WIREPEN,MUIV_TriggerValue])
    doMethodA(selpen,[MUIM_Notify,MUIA_Pendisplay_Spec,MUIV_EveryTime,grp,3,MUIM_Set,ATTR_SELCPEN,MUIV_TriggerValue])
    doMethodA(window,[MUIM_Notify,MUIA_Window_Activate,MUI_TRUE,window,3,MUIM_WriteLong,window,{cwindow}])
    doMethodA(window,[MUIM_Notify,MUIA_Window_Activate,MUI_TRUE,mcrsave,3,MUIM_Set,MUIA_Disabled,FALSE])
    doMethodA(window,[MUIM_Notify,MUIA_Window_Activate,MUI_TRUE,save,3,MUIM_Set,MUIA_Disabled,FALSE])
    doMethodA(window,[MUIM_Notify,MUIA_Window_CloseRequest,MUI_TRUE,window,3,MUIM_CallHook,closeHook,data])
    doMethodA(window,[MUIM_Notify,MUIA_Window_InputEvent,'-repeat del',grp,3,MUIM_CallHook,delHook,NIL])
    doMethodA(window,[MUIM_Notify,MUIA_Window_InputEvent,'-repeat space',app,2,MUIM_Application_ReturnID,ID_BIND])

    get(poppen,MUIA_Pendisplay_Spec,{startpen})
    set(grp,ATTR_WIREPEN,startpen)
    get(selpen,MUIA_Pendisplay_Spec,{startpen})
    set(grp,ATTR_SELCPEN,startpen)
    set(window,MUIA_Window_Open,MUI_TRUE)
    set(mcrsave,MUIA_Disabled,FALSE)
    set(save,MUIA_Disabled,FALSE)
ENDPROC

PROC closeFunc(window,aa:PTR TO LONG)
DEF doit=TRUE,data:PTR TO logic_c_data
    data:=aa[]
    IF data.changed THEN
        doit:=(Mui_RequestA(app,window,NIL,'Close Window','*_Yes|_No','Do you want to close the window\nwithout saving the circuit?',NIL) = 1)
    IF doit
        set(mcrsave,MUIA_Disabled,MUI_TRUE)
        set(save,MUIA_Disabled,MUI_TRUE)
        doMethodA(app,[OM_REMMEMBER,window])
        /*Why isn't Mui_DisposeObject(window) required?*/
    ENDIF
ENDPROC

PROC readmacros()
DEF str[40]:STRING,str2[40]:STRING,mx,j,mptr:PTR TO macro
    NEW dl.dirlist()
    dl.setdir('macros/')
    dl.read(FALSE)
    dl.sort()
    IF dl.first()
        mx:=dl.numitems()

        NEW macros[mx] /*WARNING, ONLY THE LONGS HAVE BEEN ALOCATED*/
        nmacros:=-1

        FOR j:=0 TO mx-1
            StrCopy(str,dl.obj())
            StrCopy(str2,'macros/')
            StrAdd(str2,str)
            NEW mptr
            macros[j]:=mptr
            mptr.loadmacro(str2)
            nmacros++
            EXIT dl.succ()=FALSE
        ENDFOR
    ENDIF
    rectangle:=RectangleObject,End
    doMethodA(macrolist,[OM_ADDMEMBER,rectangle])
    END dl
    dl:=NIL
ENDPROC

PROC loadmacro(path:PTR TO CHAR) OF macro
DEF handler,status,str[50]:STRING,quit,j,cmd[10]:STRING,args[40]:STRING,obj,
o,p,exitstr[40]:STRING,bmp:PTR TO bitmap
    IF handler:=Open(path,OLDFILE)
        quit:=FALSE
        self.name:=String(StrLen(path))
        StrCopy(self.name,path)
        REPEAT
            status:=ReadStr(handler,str)
            IF str[] OR (status <> -1)
                j:=InStr(str,'=')
                MidStr(cmd,str,0,j)
                MidStr(args,str,j+1)
                IF StrCmp(cmd,'Ico')
                    self.pictures[]:=loadspic(args)         /*.pictures*/
                    bmp:=pic.bitmap()
                    obj:=MUIimage(bmp)
                    self.gad:=obj                           /*.gad*/
                    IF obj
                        doMethodA(macrolist,[OM_ADDMEMBER,obj])
                    ELSE
                        WriteF('Couldn''t create macro list!!!!!\n')
                    ENDIF
                ELSEIF StrCmp(cmd,'InIco')
                    self.pictures[1]:=loadspic(args)
                ELSEIF StrCmp(cmd,'OutIco')
                    self.pictures[2]:=loadspic(args)
                ELSEIF StrCmp(cmd,'InOutIco')
                    self.pictures[3]:=loadspic(args)
                ELSEIF StrCmp(cmd,'In')
                    j:=Val(args)
                    IF j < 0                                /*.inOM*/
                        self.nin:=-j                        /*.nin*/
                        self.inOM:=TRUE
                    ELSE
                        self.nin:=j
                        self.inOM:=FALSE
                    ENDIF
                ELSEIF StrCmp(cmd,'Out')
                    j:=Val(args)
                    IF j < 0
                        self.nout:=-j                       /*.nout*/
                        self.outOM:=TRUE                    /*.outOM*/
                    ELSE
                        self.nout:=j
                        self.outOM:=FALSE
                    ENDIF
                    NEW self.values[powertwo(self.nin)]
                ELSEIF StrCmp(cmd,'Exit')
                    StrCopy(exitstr,args)
                ELSE
                    WriteF('Unknown command \s.\n',cmd)
                ENDIF
            ELSE
                quit:=TRUE
            ENDIF
        UNTIL quit
        Close(handler)
        StrCopy(args,exitstr)                            /*to be sure that values is ready,*/
        j:=0;p:=-1                                       /*we decode Exit  at the end*/
        WHILE p < EstrLen(args)         /*12 34 56*/
            o:=p+1                      /*   o p  */
            p:=InStr(args,' ',o)
            IF p = -1 THEN p:=EstrLen(args)
            MidStr(str,args,o,p-o)
            self.values[j++]:=Val(str)          /*.values*/
        ENDWHILE
    ELSE
        StringF(s,'Macro "\s" couldn''t be opened!',path)
        Raise(s)
    ENDIF
ENDPROC

PROC writecircuit(path,data:PTR TO logic_c_data,window)
DEF j,k,l,handler,oldstdout,objs:PTR TO LONG,nobjs,optr:PTR TO objet,mptr:PTR TO macro

    data.changed:=FALSE
    objs:=data.objs;nobjs:=data.nobjs

    handler:=Open(path,NEWFILE);oldstdout:=SetStdOut(handler)

    get(window,MUIA_Window_LeftEdge,{j})
    get(window,MUIA_Window_TopEdge,{k})
    get(window,MUIA_Window_Width,{u})
    get(window,MUIA_Window_Height,{v})
    WriteF('{N\d} {X\d} {Y\d} {W\d} {H\d}\n',nobjs,j,k,u,v)

    FOR j:=0 TO nobjs-1                        /*j = n° de l'objet (objs[j])*/
        optr:=objs[j]                          /*optr et mptr define the source object*/
        mptr:=optr.macro
        WriteF('[P\d,\d]',optr.x,optr.y)
        IF mptr.inOM
            WriteF(' [S\d]',optr.state)
        ENDIF
        WriteF(' [M\s]',mptr.name)
        IF mptr.nin+mptr.inOM > 0
            FOR k:= 0 TO mptr.nin-1+mptr.inOM  /*k = n° of the current input*/
                WriteF(' [D')
                IF optr.ins[k]<>NIL
                    FOR l:=0 TO nobjs-1            /*search the object linked to j[k]*/
                        EXIT optr.ins[k]=objs[l]
                        IF CtrlC() THEN JUMP stop
                    ENDFOR
                    WriteF('\d,\d]',l,optr.ind[k]) /*l = n° of the object linked to the input (objs[l])*/
                ELSE
                    WriteF(']')
                ENDIF
            ENDFOR
        ENDIF
        WriteF('\n')
    ENDFOR
stop:
    Close(handler);SetStdOut(oldstdout)
ENDPROC

PROC readcircuit(path)
DEF quit=FALSE,str[300]:STRING,optr:PTR TO objet,mptr:PTR TO macro,j,handler,status,
    o,p,com[2]:STRING,args[20]:STRING,t[10]:STRING,q,nextin,grp,gg,
    data:PTR TO logic_c_data,window,bmp:PTR TO bitmap,layoutr

    set(waitwindow,MUIA_Window_Title,'Loading circuit')
    set(wtext,MUIA_Text_Contents,'Reading file')
    set(wgauge,MUIA_Gauge_Current,0)
    set(waitwindow,MUIA_Window_Open,MUI_TRUE)

    handler:=Open(path,OLDFILE)
    status:=ReadStr(handler,str)
    IF Not(str[]) AND (status = -1) THEN
        RETURN FALSE

    window:=WindowObject,
        MUIA_Window_Title,FilePart(path),MUIA_Window_ScreenTitle, screent,
        MUIA_Window_Width, MUIV_Window_Width_Screen(50),MUIA_Window_Height, MUIV_Window_Height_Screen(50),
        MUIA_Window_ID,nextid++,
        WindowContents, grp:=NewObjectA(cl_logic_c.mcc_class,NIL,
            [VirtualFrame,MUIA_Group_LayoutHook,layoutHook,End,
        End
    data:=INST_DATA(cl_logic_c.mcc_class,grp)
    data.temp:=NIL
    layoutr:=RectangleObject,End
    doMethodA(grp,[OM_ADDMEMBER,layoutr])
    data.layoutr:=layoutr

    data.changed:=FALSE
    data.window:=window
    doMethodA(app,[OM_ADDMEMBER,window])
    doMethodA(poppen,[MUIM_Notify,MUIA_Pendisplay_Spec,MUIV_EveryTime,grp,3,MUIM_Set,ATTR_WIREPEN,MUIV_TriggerValue])
    doMethodA(selpen,[MUIM_Notify,MUIA_Pendisplay_Spec,MUIV_EveryTime,grp,3,MUIM_Set,ATTR_SELCPEN,MUIV_TriggerValue])
    doMethodA(window,[MUIM_Notify,MUIA_Window_Activate,MUI_TRUE,window,3,MUIM_WriteLong,window,{cwindow}])
    doMethodA(window,[MUIM_Notify,MUIA_Window_Activate,MUI_TRUE,mcrsave,3,MUIM_Set,MUIA_Disabled,FALSE])
    doMethodA(window,[MUIM_Notify,MUIA_Window_Activate,MUI_TRUE,save,3,MUIM_Set,MUIA_Disabled,FALSE])
    doMethodA(window,[MUIM_Notify,MUIA_Window_CloseRequest,MUI_TRUE,window,3,MUIM_CallHook,closeHook,data])
    doMethodA(window,[MUIM_Notify,MUIA_Window_InputEvent,'-repeat del',grp,3,MUIM_CallHook,delHook,NIL])
    doMethodA(window,[MUIM_Notify,MUIA_Window_InputEvent,'-repeat space',app,2,MUIM_Application_ReturnID,ID_BIND])
    get(poppen,MUIA_Pendisplay_Spec,{startpen})
    set(grp,ATTR_WIREPEN,startpen)
    get(selpen,MUIA_Pendisplay_Spec,{startpen})
    set(grp,ATTR_SELCPEN,startpen)
    set(mcrsave,MUIA_Disabled,FALSE);set(save,MUIA_Disabled,FALSE)

    p:=-1
    REPEAT
        o:=InStr(str,'{',p+1)
        IF o <> -1
            p:=InStr(str,'}',o+1)
            MidStr(com,str,o+1,1)
            MidStr(args,str,o+2,p-o-2)
            IF StrCmp(com,'N')
                data.nobjs:=Val(args)
                NEW data.objs[data.nobjs]
                FOR j:=0 TO data.nobjs-1
                    NEW optr
                    data.objs[j]:=optr
                ENDFOR
            ELSEIF StrCmp(com,'X')
                set(window,MUIA_Window_LeftEdge,Val(args))
            ELSEIF StrCmp(com,'Y')
                set(window,MUIA_Window_TopEdge,Val(args))
            ELSEIF StrCmp(com,'W')
                set(window,MUIA_Window_Width,Val(args))
            ELSEIF StrCmp(com,'H')
                set(window,MUIA_Window_Height,Val(args))
            ELSE
                WriteF('Unknown header command {\s}\n',com)
            ENDIF
        ENDIF
    UNTIL o = -1

    j:=-1

    REPEAT
        status:=ReadStr(handler,str)
        IF str[] OR (status <> -1)
            j:=j+1
            set(wgauge,MUIA_Gauge_Current,100*j/data.nobjs)
            IF j > data.nobjs
                WriteF('Sorry, But there are more objects than promised.\n' +
                       'You will probably have problems, so I suggest to close the window,\n' +
                       'correct the circuit file and load it again. Anyway, objects will miss\n' +
                       'and there may be wires pointing to them...\n')
                WriteF('[Found an object n° \d and nobjs is \d.]\n',j,data.nobjs)
                quit:=TRUE
            ELSE
                optr:=data.objs[j]
                /*We now have to decode str to optr.*/
                p:=-1
                nextin:=0
                REPEAT
                    o:=InStr(str,'[',p+1)
                    IF o <> -1
                        p:=InStr(str,']',o+1)
                        MidStr(com,str,o+1,1)
                        MidStr(args,str,o+2,p-o-2)
                        IF StrCmp(com,'S')                 /*Switches*/
                            optr.state:=Val(args)
                        ELSEIF StrCmp(com,'P')             /*Coordinates*/
                            q:=InStr(args,',')
                            MidStr(t,args,0,q)
                            optr.x:=Val(t)
                            MidStr(t,args,q+1)
                            optr.y:=Val(t)
                        ELSEIF StrCmp(com,'M')             /*macro*/
                            FOR q:=0 TO nmacros
                                mptr:=macros[q]
                                EXIT StrCmp(mptr.name,args)
                            ENDFOR
                            optr.macro:=mptr
                            NEW optr.ins[mptr.nin]
                            NEW optr.ind[mptr.nin]
                        ELSEIF StrCmp(com,'D')
                            IF p = (o+2) ->[D]
                                optr.ins[nextin]:=NIL
                                optr.ind[nextin++]:=0
                            ELSE
                                q:=InStr(args,',')
                                MidStr(t,args,0,q)
                                optr.ins[nextin]:=data.objs[Val(t)]
                                MidStr(t,args,q+1)
                                optr.ind[nextin++]:=Val(t)
                            ENDIF
                        ELSE
                            WriteF('Unknown object command [\s]\n',com)
                        ENDIF
                    ENDIF
                UNTIL o = -1
                pic:=mptr.pictures[]
                bmp:=pic.bitmap()
                optr.gad:=case(bmp)
                gg:=VGroup,Child,optr.gad,End
                IF optr.gad <> NIL
                    doMethodA(grp,[OM_ADDMEMBER,gg])
                    doMethodA(optr.gad,[MUIM_Notify,MUIA_Selected,MUIV_EveryTime,app,3,MUIM_WriteLong,FALSE,{background}])
                    doMethodA(optr.gad,[MUIM_Notify,MUIA_Pressed,FALSE,app,3,MUIM_CallHook,pressHook,optr])
                ELSE
                    Mui_RequestA(app,window,0,'Object creation',NIL,'Couldn''t create an object!',NIL)
                ENDIF
            ENDIF
        ELSE
            quit:=TRUE
            IF j < (data.nobjs-1)
                WriteF('Sorry, but there are less objects than promised.\n' +
                       'It means that too much memory has been alocated.\n' +
                       'No other problems should arise.\n')
            ENDIF
        ENDIF
    UNTIL quit
    data.temp:=NIL

    Close(handler)

    set(wtext,MUIA_Text_Contents,'Opening Window')

    set(window,MUIA_Window_Open,MUI_TRUE)

    set(waitwindow,MUIA_Window_Open,FALSE)

ENDPROC TRUE

/********************************************
*                                           *
*   writemacro(path,mcr,f0,f1,f2,f3)        *
*                                           *
*  path: name of the file to create         *
*  mcr:address of the macro object to read  *
*  fx: name of the picture files (nil,in,   *
*   out,inout)                              *
*                                           *
*   Saves a new macro on the disk           *
*                                           *
********************************************/

PROC writemacro(path,mcr:PTR TO macro,f0,f1,f2,f3)
DEF handler,oldstdout,j
    handler:=Open(path,NEWFILE)
    oldstdout:=SetStdOut(handler)
    IF mcr.inOM
        WriteF('In=\d\n',-mcr.nin)
    ELSE
        WriteF('In=\d\n',mcr.nin)
    ENDIF
    IF mcr.outOM
        WriteF('Out=\d\n',-mcr.nout)
    ELSE
        WriteF('Out=\d\n',mcr.nout)
    ENDIF
    WriteF('Exit=\d',mcr.values[])
    IF mcr.nin<>0
        FOR j:=1 TO powertwo(mcr.nin)-1
            WriteF(' \d',mcr.values[j])
        ENDFOR
    ENDIF
    WriteF('\n')
    WriteF('Ico=\s\n',f0)
    IF mcr.inOM THEN WriteF('InIco=\s\n',f1)
    IF mcr.outOM THEN WriteF('OutIco=\s\n',f2)
    IF mcr.inOM AND mcr.outOM THEN WriteF('InOutIco=\s\n',f3)
    Close(handler)
    SetStdOut(oldstdout)
ENDPROC

PROC addmacro(newmacro) /*only to add macro after they're loaded!!*/
DEF buffer:PTR TO LONG,j
    nmacros++               /*nmacros is now the number of the macro to be added*/
    NEW buffer[nmacros+1]   /*nmacros+1 is the size of the new array*/
    FOR j:=0 TO nmacros-1
        buffer[j]:=macros[j]
    ENDFOR
    END macros[nmacros]
    buffer[nmacros]:=newmacro
    macros:=buffer
ENDPROC

PROC findobj(gad,data:PTR TO logic_c_data) /*finds the address of the objet OBJECT containing the gad gadget*/
DEF myptr:PTR TO objet,j
    IF data.temp <> NIL
        RETURN NIL
    ENDIF
    FOR j:=0 TO data.nobjs-1
        myptr:=data.objs[j]
        IF myptr.gad=gad
            RETURN myptr
        ENDIF
    ENDFOR
ENDPROC NIL

PROC powertwo(expo) IS Shl(1,expo)

/********************************************
*                                           *
*   fullcalc(data,flag)                     *
*                                           *
*  flag:transmitted to calc                 *
*                                           *
*   Calculate all doors                     *
*                                           *
********************************************/

PROC fullcalc(data:PTR TO logic_c_data,flag=0)
DEF j,optr:PTR TO objet
    IF data.temp=NIL
        FOR j:=0 TO data.nobjs-1
            optr:=data.objs[j]
            optr.value:=-2          /*optr's calculation never started*/
        ENDFOR

        FOR j:=0 TO data.nobjs-1
            calc(data.objs[j],0,flag)
        ENDFOR
    ENDIF
ENDPROC

/********************************************
*                                           *
*   calc(oobj,door,flag)                    *
*                                           *
*  oobj:adress of an object we want the     *
*  value.                                   *
*  door:nb of the door to return if an      *
*   answer is asked (!The light doesn't     *
*   count!)                                 *
*  flag:FL_NODRAW if no output to the screen*
*   must be done.                           *
*                                           *
*   Calculate the value of oobj. Changes    *
*   MUIA_Bitmap_Bitmap if required.         *
*                                           *
********************************************/

PROC calc(oobj:PTR TO objet,door=0,flag=NIL)
DEF j,mptr:PTR TO macro,input,power,t
    IF oobj=NIL
        RETURN 0
    ENDIF
    mptr:=oobj.macro
    IF oobj.value=-1
        bip()
        oobj.value:=0
        RETURN oobj.value
    ENDIF
    IF oobj.value <> -2
        RETURN Sign(oobj.value AND powertwo(door-mptr.outOM))
    ENDIF
    oobj.value:=-1             /*oobjs' calculation started*/
    input:=0
    power:=1
    FOR j:=0 TO mptr.nin-1
        IF (j = 0) AND (mptr.inOM)
            input:=-oobj.state
        ELSE
            input:=input+(power*calc(oobj.ins[j],oobj.ind[j],flag))
        ENDIF
        power:=Shl(power,1)
    ENDFOR
    oobj.value:=mptr.values[input]
    IF mptr.outOM
        IF flag <> FL_NODRAW
            j:=0
            IF oobj.value AND 1
                j:=2
            ENDIF
            IF oobj.state THEN j++
            pic:=mptr.pictures[j]
            setbitmap(oobj.gad,pic.bitmap())
        ENDIF
        RETURN Sign(oobj.value AND powertwo(door+1))
    ENDIF
ENDPROC Sign(oobj.value AND powertwo(door))

PROC savereq(title,path=NIL)
    IF path=NIL THEN path:='Macros/'
    get(toolswin,MUIA_Window_Window,{u})
    filereq:=AllocAslRequest(ASL_FILEREQUEST,
                            [ASL_HAIL,      title,
                             ASL_OKTEXT,    'Save',
                             ASL_DIR,       path,
                             ASL_WINDOW,    u,
                             ASL_FUNCFLAGS, FILF_SAVE,
                             NIL])
    IF filereq=NIL
        Mui_RequestA(app,toolswin,0,title,NIL,'Couldn''t create Asl requester!',NIL)
        RETURN FALSE
    ELSE
        IF AslRequest(filereq,NIL)
            StrCopy(s,filereq.drawer)
            AddPart(s,filereq.file,StrMax(s))
            SetStr(s,StrLen(s))
            FreeAslRequest(filereq)
            RETURN TRUE
        ENDIF
        FreeAslRequest(filereq)
    ENDIF
ENDPROC FALSE
PROC loadreq(title,oktext=NIL,path=NIL)
    IF oktext=NIL THEN oktext:='Select'
    IF path=NIL THEN path:='Images/'
    get(toolswin,MUIA_Window_Window,{u})
    filereq:=AllocAslRequest(ASL_FILEREQUEST,
                            [ASL_HAIL,      title,
                             ASL_OKTEXT,    oktext,
                             ASL_DIR,       path,
                             ASL_WINDOW,    u,
                             NIL])
    IF filereq=NIL
        Mui_RequestA(app,toolswin,0,title,NIL,'Couldn''t create Asl requester!',NIL)
        RETURN FALSE
    ELSE
        IF AslRequest(filereq,NIL)
            StrCopy(s,filereq.drawer)
            AddPart(s,filereq.file,StrMax(s))
            SetStr(s,StrLen(s))
            FreeAslRequest(filereq)
            RETURN TRUE
        ENDIF
        FreeAslRequest(filereq)
    ENDIF
ENDPROC FALSE

/****************************************
*                                       *
*   calcmacro(data,dr,state)            *
*                                       *
*  dr:nb of the input (nmIn[dr])        *
*  value:its value                      *
*                                       *
*   fills nmMacro.values                *
*                                       *
****************************************/

PROC calcmacro(data:PTR TO logic_c_data,dr,state)
DEF optr:PTR TO objet,j,result,fact,mptr:PTR TO macro
    optr:=nmIn[dr]
    optr.state:=state
    IF dr = (nmMacro.nin-1)
        FOR j:=0 TO data.nobjs-1
            optr:=data.objs[j]
            optr.value:=-2
        ENDFOR

        fact:=1;result:=0

        IF nmMacro.outOM
            optr:=nmOuta
            mptr:=optr.macro
            result:=result+(fact*calc(optr,mptr.outOM,FL_NODRAW))
            fact:=fact*2
        ENDIF
        IF (nmMacro.nout+nmMacro.outOM)>0
            FOR j:=0 TO nmMacro.nout-1
                optr:=nmOut[j]
                mptr:=optr.macro
                result:=result+(fact*calc(optr,mptr.outOM,FL_NODRAW))
                fact:=fact*2
            ENDFOR
        ENDIF
        nmMacro.values[nmNin++]:=result
    ELSE
        calcmacro(data,dr+1,FALSE)
        calcmacro(data,dr+1,TRUE)
    ENDIF
ENDPROC

PROC end() OF macro /*macro class destructor*/
    END self.values[powertwo(self.nin)]
    DisposeLink(self.name)
    pic:=self.pictures[0]
    IF pic THEN END pic
    pic:=self.pictures[1]
    IF pic THEN END pic
    pic:=self.pictures[2]
    IF pic THEN END pic
    pic:=self.pictures[3]
    IF pic THEN END pic
ENDPROC

PROC setbitmap(object,bitmap)
DEF gg,last
    get(object,MUIA_Bitmap_Bitmap,{last})
    IF last = bitmap THEN RETURN
    set(object,MUIA_Bitmap_Bitmap,bitmap)

    get(object,MUIA_Parent,{gg})
    doMethodA(gg,[MUIM_Group_InitChange])
    doMethodA(gg,[OM_REMMEMBER,object])
    doMethodA(gg,[OM_ADDMEMBER,object])
    doMethodA(gg,[MUIM_Group_ExitChange])
ENDPROC

/*relayout: causes a call to my custom layout hook displaying/hiding an invisble rectangle*/

PROC relayout(group)
DEF data:PTR TO logic_c_data,p
    data:=INST_DATA(cl_logic_c.mcc_class,group)
    get(data.layoutr,MUIA_ShowMe,{p})
    set(data.layoutr,MUIA_ShowMe,1-p)
ENDPROC                 
