/************************************************************************
 * TITLE:         JAZENV.C             *
 * PROJECT:    JAGUAR/JAZ           *
 * FUNCTION:      JAZ ENVELOPE EDIT MODULE            *
 * PROGRAMMER:    Andreas Binner       *
 * DATE:       6/95              *
 *                         *
 *              COPYRIGHT 1993,1994 Atari U.S. Corporation              *
 *          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
 *          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
 *        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
 *                            ALL RIGHTS RESERVED.                      *
 *                         *
 ************************************************************************/

#include <stdarg.h>
#include "portab.h"
#include "slibc.h"
#include "glib.h"
#include "gemlib.h"
#include "jazobj.h"
#include "ptchptch.h"
#include "jazsyn.h"
#include "dos.h"
#include "jazutil.h"
#include "jazenv.h"
#include "algobj.h"

#define ENV_BOX   0
#define ENV_TITLE 1
#define ENV_ENV 2
#define ENV_POINT 3
#define ENV_AMPL 4
#define ENV_TIME 5
#define ENV_LOOP 6
#define ENV_BAR1 7
#define ENV_ADD 8
#define ENV_DELETE 9
#define  ENV_CHOOSE 10
#define ENV_LOCK 11
#define ENV_BAR 12
#define ENV_OK 13
#define ENV_CANCEL 14

#define VOL_BOX   0
#define VOL_TITLE 1
#define VOL_DELAY 2
#define VOL_PAN   3
#define VOL_VOL   4
#define VOL_BAR   5
#define VOL_OK 6

#define AUSW_BOX  0
#define AUSW_TITLE   1
#define AUSW_FRAME   2
#define AUSW_ENV1 3
#define AUSW_ENV2 4
#define AUSW_ENV3 5
#define AUSW_ENV4 6
#define AUSW_ENV5 7
#define AUSW_SLIDER  8
#define AUSW_BAR  9
#define AUSW_OK      10
#define AUSW_CANCEL 11

typedef struct
{
   LONG type;
   LONG r_flags;
   LONG wave_poi1;
   LONG pitch1;
   LONG loc1;
   LONG wave_poi2;
   LONG pitch2;
   LONG loc2;
   ENVPARA env[3];

   LONG filter_table,delay,pan,volume;
} PARAM3;

VOID handle_modifier(OBJECT *tree,WORD obj,POPUPINFO *info);
VOID adjust_volume(OBJECT *tree,WORD obj,POPUPINFO *info);
VOID handle_env(OBJECT *tree,WORD obj,POPUPINFO *info);
VOID env_change_point(OBJECT *tree,WORD obj,SLIDEINFO *info);
VOID env_change_value(OBJECT *tree,WORD obj,SLIDEINFO *info);
WORD env_button_cancel(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
WORD env_button_ok(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
WORD env_button_add(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
WORD env_button_delete(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
WORD env_button_lock(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
VOID setup_env(ENVINFO *info);
VOID set_limits(WORD p,WORD anz);
VOID delay_change(OBJECT *tree,WORD obj,SLIDEINFO *info);
VOID pan_change(OBJECT *tree,WORD obj,SLIDEINFO *info);
VOID vol_change(OBJECT *tree,WORD obj,SLIDEINFO *info);
WORD vol_button_ok(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
WORD active_envelopes(VOID);
VOID handle_choose(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
VOID setup_chooser(WORD start);
WORD choose_envelope(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3);
VOID ausw_change(OBJECT *tree,WORD obj,SLIDEINFO *info);
VOID handle_rom(OBJECT *tree,WORD obj,POPUPINFO	*info,WORD osc,WORD	type);

PARAM3 old_patch;
EXTERN PARAM3 *curr_patch;
EXTERN WORD scrn_w, scrn_h;
EXTERN BYTE *samplenameslist;
EXTERN ENVTAB env_table[];
EXTERN WORD envslot_cnt;
EXTERN OBJECT algtree[];
EXTERN ENVSLOT dsp_envslots[];
EXTERN LONG *org_work_addr;

OBJECT envtree[20],voltree[10],auswtree[20];
WORD type,max_points;
LONG zero=0L;

VOID handle_modifier(OBJECT *tree,WORD obj,POPUPINFO *info)
{

   type=info->index;
   if (!type)
   {
      switch(obj)
      {
         case ALG_FILTERENV:
         case ALG_OSC1ENV:
            v_dark_tree(algtree);
            handle_constvalue(tree,obj,3);
         break;

         case ALG_DISTENV:
            v_dark_tree(algtree);
            handle_constvalue(tree,obj,4);
         break;

         case ALG_ATTNENV:
            v_dark_tree(algtree);
            handle_constvalue(tree,obj,2);
         break;

         default:
            return;
         break;
      }
      objc_draw(algtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      objc_outline(tree, obj, NIL);
      return;
   }
   memcpy((BYTE *)&old_patch,(BYTE *) curr_patch, (LONG)sizeof(PARAM3));

   if (!(info->user_defined&0x8000))
   {
      type=info->user_defined-2;
      max_points=32;
      org_work_addr=0L;
      if (dspenv2temp(curr_patch->env[type].point, type)!=FAILURE)
      {
         envtree[ENV_ENV].ob_spec.env->patch_env=&curr_patch->env[type];
         calc_envelope(envtree[ENV_ENV].ob_spec.env,0);
         setup_env(envtree[ENV_ENV].ob_spec.env);
         handle_env(tree,obj,info);
      }
   }
   else
   {

/* Call ROM-Wave edit page for LFO
*/

      handle_rom(tree,obj,info,info->user_defined&0x7fff,0);
   }

   objc_draw(algtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   objc_outline(tree, obj, NIL);
}


VOID build_jazenv(VOID)
{

   objc_xadd(auswtree, NIL, AUSW_BOX,
      G_BOX, -1, -1,
      97, 10, 190, 185,
      IS3DOBJ|NONE, NORMAL,
      0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_TITLE,
         G_XBOXTEXT, -1, -1,
         0, 0, 112, 8,
         IS3DOBJ|NONE, NORMAL,
         T_OB_LATTACH, AUSW_BOX, 4,
         T_OB_RATTACH, AUSW_BOX, 4,
         T_OB_UATTACH, AUSW_BOX, 2,
         T_BX_TEXT, "CHOOSE ENVELOPE",
         T_BX_FONTID, FNT_SMALL,
         T_BX_ALIGN, TE_CNTR,
         0);

      objc_xadd(auswtree, AUSW_BOX, AUSW_FRAME,
         G_BOX, -1, -1,
         0, 0, 75, 37,
         FRAME, NORMAL,
         T_OB_UATTACH, AUSW_TITLE, 10,
         T_OB_LATTACH, AUSW_BOX, 2,
         0);

      objc_xadd(auswtree, AUSW_BOX, AUSW_ENV1,
         G_XENVELOPE, -1, -1,
         4, 4, 64, 25,
         NONE, NORMAL,
         T_OB_UATTACH, AUSW_TITLE, 16,
         T_OB_LATTACH, AUSW_BOX, 8,
         0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_ENV2,
         G_XENVELOPE, -1, -1,
         0, 0, 64, 25,
         NONE, NORMAL,
         T_OB_UATTACH, AUSW_ENV1, 10,
         T_OB_LATTACH, AUSW_BOX, 8,
         0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_ENV3,
         G_XENVELOPE, -1, -1,
         0, 0, 64, 25,
         NONE, NORMAL,
         T_OB_UATTACH, AUSW_ENV2, 6,
         T_OB_LATTACH, AUSW_BOX, 8,
         0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_ENV4,
         G_XENVELOPE, -1, -1,
         0, 0, 64, 25,
         NONE, NORMAL,
         T_OB_UATTACH, AUSW_ENV3, 6,
         T_OB_LATTACH, AUSW_BOX, 8,
         0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_ENV5,
         G_XENVELOPE, -1, -1,
         0, 0, 64, 25,
         NONE, NORMAL,
         T_OB_UATTACH, AUSW_ENV4, 6,
         T_OB_LATTACH, AUSW_BOX, 8,
         0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_SLIDER,
         G_XREALSLIDER, -1, -1,
         0, 6, 20, 145,
         JOYPAD|SELECTABLE, NORMAL,
         T_OB_UATTACH, AUSW_TITLE, 10,
         T_OB_LATTACH, AUSW_ENV1, 10,
         T_OB_RIGHT, AUSW_BAR,
         T_OB_LEFT, AUSW_BAR,
         T_SLIDE_SLNAME, "",
         T_SLIDE_MIN, 0L,
         T_SLIDE_MAX, 0x7fL,
         T_SLIDE_CALLBK, ausw_change,
         0);
      objc_xadd(auswtree, AUSW_BOX, AUSW_BAR,
         G_XBAR, -1, -1,
         6, 0, 70, 40,
         IS3DOBJ|JOYPAD|SELECTABLE, NORMAL,
         T_OB_LEFT, AUSW_SLIDER,
         T_OB_RIGHT, AUSW_SLIDER,
         T_OB_UATTACH, AUSW_TITLE, 50,
         T_OB_LATTACH, AUSW_SLIDER, 6,
         T_BA_NUM, 2,
         T_BA_FIRST, 1,
         0);
         objc_xadd(auswtree, AUSW_BAR, AUSW_OK,
            G_XBUTTON, -1, -1,
            0, 2, 60, 12,
            ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
            T_BT_TEXT, "OK",
            T_BT_BGCOLOR, 0,
            T_BT_TXTCOLOR, 1,
            T_BT_FONTID, 1,
            T_BT_SMCHAR, '1',
            T_BT_CALLBK, choose_envelope,
            T_OB_LATTACH, AUSW_BAR, 2,
            T_OB_UATTACH, AUSW_BAR, 2,
            0);
         objc_xadd(auswtree, AUSW_BAR, AUSW_CANCEL,
            G_XBUTTON, -1, -1,
            0, 2, 60, 12,
            ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
            T_BT_TEXT, "Cancel",
            T_BT_BGCOLOR, 0,
            T_BT_TXTCOLOR, 1,
            T_BT_FONTID, 1,
            T_BT_SMCHAR, '2',
            T_BT_CALLBK, vol_button_ok,
            T_OB_LATTACH, AUSW_BAR, 2,
            T_OB_UATTACH, AUSW_OK, 4,
            0);


   objc_xadd(voltree, NIL, VOL_BOX,
      G_BOX, -1, -1,
      117, 20, 150, 160,
      IS3DOBJ|NONE, NORMAL,
      0);
      objc_xadd(voltree, VOL_BOX, VOL_TITLE,
         G_XBOXTEXT, -1, -1,
         0, 0, 112, 14,
         IS3DOBJ|NONE, NORMAL,
         T_OB_LATTACH, VOL_BOX, 6,
         T_OB_RATTACH, VOL_BOX, 6,
         T_OB_UATTACH, VOL_BOX, 2,
         T_BX_TEXT, "MIXER PARAMETERS",
         T_BX_FONTID, FNT_SMALL,
         T_BX_ALIGN, TE_CNTR,
         0);
      objc_xadd(voltree, VOL_BOX, VOL_DELAY,
         G_XREALSLIDER, -1, -1,
         0, 6, 40, 96,
         JOYPAD|SELECTABLE, NORMAL,
         T_OB_UATTACH, VOL_TITLE, 10,
         T_OB_LATTACH, VOL_BOX, 10,
         T_OB_DOWN, VOL_BAR,
         T_OB_RIGHT, VOL_PAN,
         T_OB_LEFT, VOL_VOL,
         T_SLIDE_SLNAME, "DELAY",
         T_SLIDE_MIN, 0L,
         T_SLIDE_MAX, 0x7fL,
         T_SLIDE_CALLBK, delay_change,
         0);
      objc_xadd(voltree, VOL_BOX, VOL_PAN,
         G_XREALSLIDER, -1, -1,
         0, 6, 40, 96,
         JOYPAD|SELECTABLE, NORMAL,
         T_OB_UATTACH, VOL_TITLE, 10,
         T_OB_LATTACH, VOL_DELAY, 6,
         T_OB_LEFT, VOL_DELAY,
         T_OB_RIGHT, VOL_VOL,
         T_OB_DOWN, VOL_BAR,
         T_SLIDE_SLNAME, "PAN",
         T_SLIDE_MIN, 0L,
         T_SLIDE_MAX, 0x7fL,
         T_SLIDE_CALLBK, pan_change,
         0);
      objc_xadd(voltree, VOL_BOX, VOL_VOL,
         G_XREALSLIDER, -1, -1,
         0, 6, 40, 96,
         JOYPAD|SELECTABLE, NORMAL,
         T_OB_UATTACH, VOL_TITLE, 10,
         T_OB_LATTACH, VOL_PAN, 6,
         T_OB_LEFT, VOL_PAN,
         T_OB_RIGHT, VOL_DELAY,
         T_OB_DOWN, VOL_BAR,
         T_SLIDE_SLNAME, "VOLUME",
         T_SLIDE_MIN, 0L,
         T_SLIDE_MAX, 0x7fffL,
         T_SLIDE_CALLBK, vol_change,
         0);

      objc_xadd(voltree, VOL_BOX, VOL_BAR,
         G_XBAR, -1, -1,
         6, 0, scrn_w-12, 18,
         IS3DOBJ|JOYPAD|SELECTABLE, NORMAL,
         T_OB_UP, VOL_PAN,
         T_OB_DOWN, VOL_PAN,
         T_OB_UATTACH, VOL_PAN, 6,
         T_OB_LATTACH, VOL_BOX, 6,
         T_OB_RATTACH, VOL_BOX, 6,
         T_BA_NUM, 1,
         T_BA_FIRST, 1,
         0);
         objc_xadd(voltree, VOL_BAR, VOL_OK,
            G_XBUTTON, -1, -1,
            0, 2, 70, 12,
            ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
            T_BT_TEXT, "OK",
            T_BT_BGCOLOR, 0,
            T_BT_TXTCOLOR, 1,
            T_BT_FONTID, 1,
            T_BT_SMCHAR, '1',
            T_BT_CALLBK, vol_button_ok,
            T_OB_LATTACH, VOL_BAR, 20,
            T_OB_RATTACH, VOL_BAR, 20,
            T_OB_UATTACH, VOL_BAR, 1,
            0);


   objc_xadd(envtree, NIL, ENV_BOX,
      G_BOX, -1, -1,
      10, 10, scrn_w - 20, scrn_h - 20,
      IS3DOBJ|NONE, NORMAL,
      0);

      objc_xadd(envtree, ENV_BOX, ENV_TITLE,
         G_XBOXTEXT, -1, -1,
         0, 0, scrn_w-12, 14,
         IS3DOBJ|NONE, NORMAL,
         T_OB_LATTACH, ENV_BOX, 6,
         T_OB_RATTACH, ENV_BOX, 6,
         T_OB_UATTACH, ENV_BOX, 2,
         T_BX_TEXT, "ENVELOPE EDITOR",
         T_BX_FONTID, FNT_SMALL,
         T_BX_ALIGN, TE_CNTR,
         0);

      objc_xadd(envtree, ENV_BOX, ENV_ENV,
         G_XENVELOPE, -1, -1,
         0, 0, 256, 100,
         NONE, NORMAL,
         T_OB_UATTACH, ENV_TITLE, 6,
         T_OB_LATTACH, ENV_BOX, 16,
         0);
      envtree[ENV_ENV].ob_spec.env->p_obj=ENV_POINT;
      envtree[ENV_ENV].ob_spec.env->t_obj=ENV_TIME;
      envtree[ENV_ENV].ob_spec.env->a_obj=ENV_AMPL;

      objc_xadd(envtree, ENV_BOX, ENV_POINT,
         G_XTEXTEDIT, -1, -1,
         0, 6, 65, 20,
         JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
         T_OB_DOWN, ENV_AMPL,
         T_OB_UP, ENV_BAR,
         T_OB_UATTACH, ENV_TITLE, 6,
         T_OB_LATTACH, ENV_ENV, 10,
         T_EDIT_NAME, "POINT",
         T_EDIT_MAX, (LONG)(envtree[ENV_ENV].ob_spec.env->points+1),
         T_EDIT_MAXSIZE, 6,
         T_EDIT_FONTID, 0,
         T_EDIT_CALLBK, env_change_point,
         T_EDIT_DATA, "000000",
         T_EDIT_TYPE, 1,
         0);

      objc_xadd(envtree, ENV_BOX, ENV_AMPL,
         G_XTEXTEDIT, -1, -1,
         0, 6, 65, 20,
         JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
         T_OB_DOWN, ENV_TIME,
         T_OB_UP, ENV_POINT,
         T_OB_UATTACH, ENV_POINT, 6,
         T_OB_LATTACH, ENV_ENV, 10,
         T_EDIT_NAME, "AMPLITUDE",
         T_EDIT_MAX, 32767L,
         T_EDIT_MAXSIZE, 6,
         T_EDIT_FONTID, 0,
         T_EDIT_CALLBK, env_change_value,
         T_EDIT_DATA, "000000",
         T_EDIT_TYPE, 1,
         0);
         
      objc_xadd(envtree, ENV_BOX, ENV_TIME,
         G_XTEXTEDIT, -1, -1,
         0, 6, 65, 20,
         JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
         T_OB_UP, ENV_AMPL,
         T_OB_DOWN, ENV_LOOP,
         T_OB_UATTACH, ENV_AMPL, 6,
         T_OB_LATTACH, ENV_ENV, 10,
         T_EDIT_NAME, "TIME IN MS",
         T_EDIT_MAX, 32767L,
         T_EDIT_MAXSIZE, 6,
         T_EDIT_FONTID, 0,
         T_EDIT_CALLBK, env_change_value,
         T_EDIT_DATA, "000000",
         T_EDIT_TYPE, 1,
         0);

      objc_xadd(envtree, ENV_BOX, ENV_LOOP,
         G_XTEXTEDIT, -1, -1,
         0, 6, 65, 20,
         JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
         T_OB_UP, ENV_TIME,
         T_OB_RIGHT, ENV_BAR1,
         T_OB_DOWN, ENV_BAR,
         T_OB_LEFT, ENV_LOCK,
         T_OB_UATTACH, ENV_TIME, 6,
         T_OB_LATTACH, ENV_ENV, 10,
         T_EDIT_NAME, "LOOP x BACK",
         T_EDIT_MAX, (LONG)(envtree[ENV_ENV].ob_spec.env->points-1),
         T_EDIT_MAXSIZE, 6,
         T_EDIT_FONTID, 0,
         T_EDIT_CALLBK, env_change_value,
         T_EDIT_DATA, "000000",
         T_EDIT_TYPE, 1,
         0);

      objc_xadd(envtree, ENV_BOX, ENV_BAR1,
         G_XBAR, -1, -1,
         6, 0, 220, 16,
         IS3DOBJ|JOYPAD|SELECTABLE, NORMAL,
         T_OB_UP, ENV_BAR,
         T_OB_DOWN, ENV_BAR,
         T_OB_RIGHT, ENV_LOCK,
         T_OB_LEFT, ENV_LOOP,
         T_OB_UATTACH, ENV_ENV, 4,
         T_OB_LATTACH, ENV_BOX, 6,
         T_BA_NUM, 3,
         T_BA_FIRST, 1,
         0);

      objc_xadd(envtree, ENV_BAR1, ENV_ADD,
         G_XBUTTON, -1, -1,
         0, 2, 70, 9,
         ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
         T_BT_TEXT, "ADD POINT",
         T_BT_BGCOLOR, 0,
         T_BT_TXTCOLOR, 1,
         T_BT_FONTID, 0,
         T_BT_SMCHAR, '1',
         T_BT_CALLBK, env_button_add,
         T_OB_LATTACH, ENV_BAR1, 4,
         T_OB_UATTACH, ENV_BAR1, 1,
         0);

      objc_xadd(envtree, ENV_BAR1, ENV_DELETE,
         G_XBUTTON, -1, -1,
         0, 2, 65, 9,
         ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
         T_BT_TEXT, "DEL POINT",
         T_BT_BGCOLOR, 0,
         T_BT_TXTCOLOR, 1,
         T_BT_FONTID, 0,
         T_BT_SMCHAR, '2',
         T_BT_CALLBK, env_button_delete,
         T_OB_LATTACH, ENV_ADD, 4,
         T_OB_UATTACH, ENV_BAR1, 1,
         0);

      objc_xadd(envtree, ENV_BAR1, ENV_CHOOSE,
         G_XBUTTON, -1, -1,
         0, 2, 55, 9,
         ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
         T_BT_TEXT, "CHOOSE",
         T_BT_BGCOLOR, 0,
         T_BT_TXTCOLOR, 1,
         T_BT_FONTID, 0,
         T_BT_SMCHAR, '3',
         T_BT_CALLBK, handle_choose,
         T_OB_LATTACH, ENV_DELETE, 4,
         T_OB_UATTACH, ENV_BAR1, 1,
         0);

      objc_xadd(envtree, ENV_BOX, ENV_LOCK,
         G_XBUTTON, -1, -1,
         0, 2, 40, 12,
         IS3DOBJ|SELECTABLE|JOYPAD|CHECKBOX, NORMAL,
         T_OB_LEFT, ENV_BAR1,
         T_OB_RIGHT, ENV_LOOP,
         T_OB_UP, ENV_LOOP,
         T_OB_DOWN, ENV_BAR,
         T_BT_TEXT, "LOCK",
         T_BT_BGCOLOR, 0,
         T_BT_TXTCOLOR, 1,
         T_BT_FONTID, 0,
         T_BT_SMCHAR, '3',
         T_BT_CALLBK, env_button_lock,
         T_OB_LATTACH, ENV_BAR1, 6,
         T_OB_UATTACH, ENV_ENV, 6,
         0);


      objc_xadd(envtree, ENV_BOX, ENV_BAR,
         G_XBAR, -1, -1,
         6, 0, scrn_w-12, 18,
         IS3DOBJ|JOYPAD|SELECTABLE, NORMAL,
         T_OB_UP, ENV_BAR1,
         T_OB_DOWN, ENV_BAR1,
         T_OB_UATTACH, ENV_BAR1, 6,
         T_OB_LATTACH, ENV_BOX, 6,
         T_OB_RATTACH, ENV_BOX, 6,
         T_BA_NUM, 2,
         T_BA_FIRST, 1,
         0);
         objc_xadd(envtree, ENV_BAR, ENV_OK,
            G_XBUTTON, -1, -1,
            0, 2, 70, 12,
            ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
            T_BT_TEXT, "OK",
            T_BT_BGCOLOR, 0,
            T_BT_TXTCOLOR, 1,
            T_BT_FONTID, 1,
            T_BT_SMCHAR, '1',
            T_BT_CALLBK, env_button_ok,
            T_OB_LATTACH, ENV_BAR, 6,
            T_OB_UATTACH, ENV_BAR, 1,
            0);
         objc_xadd(envtree, ENV_BAR, ENV_CANCEL,
            G_XBUTTON, -1, -1,
            0, 2, 70, 12,
            ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
            T_BT_TEXT, "Cancel",
            T_BT_BGCOLOR, 0,
            T_BT_TXTCOLOR, 1,
            T_BT_FONTID, 1,
            T_BT_SMCHAR, '2',
            T_BT_CALLBK, env_button_cancel,
            T_OB_LATTACH, ENV_OK, 6,
            T_OB_UATTACH, ENV_BAR, 1,
            0);
}

VOID handle_env(OBJECT *tree,WORD obj,POPUPINFO *info)
{

   objc_draw(envtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   form_xdo(envtree, ENV_BAR);

}


VOID env_change_point(OBJECT *tree,WORD obj,SLIDEINFO *info)
{
   envtree[ENV_ENV].ob_spec.env->curr_point=envtree[ENV_POINT].ob_spec.textedit->value;
   setup_env(envtree[ENV_ENV].ob_spec.env);
   objc_draw(envtree, ENV_ENV, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}

VOID env_change_value(OBJECT *tree,WORD obj,SLIDEINFO *sinfo)
{
   WORD p;
   ENVINFO *info;

   info=envtree[ENV_ENV].ob_spec.env;
   if (info->locked)
   {
      p=envtree[ENV_POINT].ob_spec.textedit->value;
      if (!p && obj==ENV_AMPL)
      {
         info->patch_env->curr=(envtree[ENV_AMPL].ob_spec.textedit->value<<15);
         calc_envelope(info,0);
         objc_draw(envtree, ENV_ENV, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      }
      if (p==envtree[ENV_ENV].ob_spec.env->points-1 && obj==ENV_TIME)
      {
         info->time[p]=(envtree[ENV_TIME].ob_spec.textedit->value<<15);
         calc_envelope(info,1);
         objc_draw(envtree, ENV_ENV, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      }
   }
   else
   {
      p=envtree[ENV_POINT].ob_spec.textedit->value;
      info->ampl[p]=(envtree[ENV_AMPL].ob_spec.textedit->value<<15);
      info->time[p]=(envtree[ENV_TIME].ob_spec.textedit->value<<15);
      info->loop=envtree[ENV_LOOP].ob_spec.textedit->value;

      if (p>0)
         if (info->time[p]<info->time[p-1])
            info->time[p]=info->time[p-1];
      calc_envelope(envtree[ENV_ENV].ob_spec.env,1);
      objc_draw(envtree, ENV_ENV, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   }
}



WORD env_button_cancel(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{

   memcpy((BYTE *)curr_patch,(BYTE *)&old_patch,84L);
   cancel_tempenv();
   return -1;
}

WORD env_button_ok(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   temp2dspenv(2 * (envtree[ENV_ENV].ob_spec.env->points - 1),
             curr_patch->env[type].curr,
             curr_patch->env[type].release);
   return -1;
}



LONG labs(LONG v)
{
   if (v<0L)
      return (-v);
   else
      return (v);
}

VOID set_limits(WORD p,WORD anz)
{
	if (!p)
	{
		envtree[ENV_TIME].ob_spec.textedit->min=0;
		envtree[ENV_TIME].ob_spec.textedit->max=0;
	}
	else
	{
		envtree[ENV_TIME].ob_spec.textedit->min=envtree[ENV_ENV].ob_spec.env->time[p-1]>>15;
		if (p==anz-1)
			envtree[ENV_TIME].ob_spec.textedit->max=32767L;
		else
			envtree[ENV_TIME].ob_spec.textedit->max=envtree[ENV_ENV].ob_spec.env->time[p+1]>>15;
	}
	if (p==anz-1)
	{
		envtree[ENV_AMPL].ob_spec.textedit->max=0;
		envtree[ENV_AMPL].ob_spec.textedit->min=0;
	}
	else
	{
		envtree[ENV_AMPL].ob_spec.textedit->max=32767L;
		envtree[ENV_AMPL].ob_spec.textedit->min=0;
	}
}

VOID setup_env(ENVINFO *info)
{
   WORD p,anz;
   ENVPARA *env;

	env=info->patch_env;
	p=envtree[ENV_POINT].ob_spec.textedit->value;
	anz=envtree[ENV_ENV].ob_spec.env->points;
	
	envtree[ENV_LOOP].ob_spec.textedit->value=(LONG)info->loop;
	
	envtree[ENV_AMPL].ob_spec.textedit->value=envtree[ENV_ENV].ob_spec.env->ampl[p]>>15;
	objc_draw(envtree, ENV_AMPL, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	envtree[ENV_TIME].ob_spec.textedit->value=envtree[ENV_ENV].ob_spec.env->time[p]>>15;
	set_limits(p,anz);
	
	objc_draw(envtree, ENV_TIME, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	
	if (anz==max_points)
	  envtree[ENV_ADD].ob_state|=DISABLED;
	else
	  envtree[ENV_ADD].ob_state&=~DISABLED;
	
	if (!p || p==anz-1 || anz<=3)
	  envtree[ENV_DELETE].ob_state|=DISABLED;
	else
	  envtree[ENV_DELETE].ob_state&=~DISABLED;
	
	
	objc_draw(envtree, ENV_ADD, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(envtree, ENV_DELETE, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}


VOID calc_envelope(ENVINFO *info,WORD f)
{
   LONG old,new,slope,dest,j,t;
   LONG *poi;
   ENVPARA *para;

   para=info->patch_env;
   if (!f)
   {
      old=info->ampl[0]=para->curr;
      t=info->time[0]=0L;

      j=1;
      poi=para->point;

      for(;;)
      {
         slope=(*poi++);
         if (!slope) slope=0x8000L;
         dest=(*poi++);
         if (dest>=0x40000000L)
         {
            info->loop=((WORD)(dest&0xffff)-1)/2;
            break;
         }

         new=info->ampl[j]=dest;
         t+=labs(new-old)/(labs(slope)>>15)/3L;
         info->time[j++]=t;

         old=new;
      }
      slope=para->release;
      if (!slope) slope=0x8000L;

      new=info->ampl[j]=0L;
      t+=labs(new-old)/(labs(slope)>>15)/3L;
      info->time[j++]=t;

      info->points=j;


      envtree[ENV_POINT].ob_spec.textedit->max=j-1;
      envtree[ENV_LOOP].ob_spec.textedit->max=j-1;
   }
   else
   {
      old=para->curr=info->ampl[0];
      poi=para->point;

      for (j=1;j<info->points-1;j++)
      {
         new=info->ampl[j];
         t=info->time[j]-info->time[j-1];
         if (!t)  t=1L;

         slope=((new-old)/3L/t)<<15;
         if (!slope)
            slope=((new-old+0x8000)/3L/t)<<15;
         *poi++=slope;
         *poi++=info->ampl[j];
         old=new;
      }
      *poi++=zero;
      *poi=0x40000000+2L*(LONG)info->loop+1L;
      t=info->time[j]-info->time[j-1];
      if (t<0xa0000L)   t=0xa0000L;
      para->release=(-new/3L/t)<<15;
   }

}

WORD env_button_lock(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   envtree[ENV_ENV].ob_spec.env->locked=tree[obj].ob_state&SELECTED;
}

WORD env_button_add(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   WORD p,anz,i;

   p=envtree[ENV_POINT].ob_spec.textedit->value;
   anz=envtree[ENV_ENV].ob_spec.env->points;

   if (anz<max_points)
   {
      anz++;
      if (!p)
         p++;

      for (i=max_points-1;i>p;i--)
      {
         envtree[ENV_ENV].ob_spec.env->time[i]=envtree[ENV_ENV].ob_spec.env->time[i-1];
         envtree[ENV_ENV].ob_spec.env->ampl[i]=envtree[ENV_ENV].ob_spec.env->ampl[i-1];
      }


      envtree[ENV_ENV].ob_spec.env->time[p]=(envtree[ENV_ENV].ob_spec.env->time[p+1]-
                                    envtree[ENV_ENV].ob_spec.env->time[p-1])/2+
                                    envtree[ENV_ENV].ob_spec.env->time[p-1];
      envtree[ENV_ENV].ob_spec.env->ampl[p]=(envtree[ENV_ENV].ob_spec.env->ampl[p+1]-
                                    envtree[ENV_ENV].ob_spec.env->ampl[p-1])/2+
                                    envtree[ENV_ENV].ob_spec.env->ampl[p-1];

      envtree[ENV_ENV].ob_spec.env->points=anz;
      envtree[ENV_POINT].ob_spec.textedit->max=anz-1;
      envtree[ENV_LOOP].ob_spec.textedit->max=anz-1;
      calc_envelope(envtree[ENV_ENV].ob_spec.env,1);
/*    objc_draw(envtree, ENV_TIME, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      objc_draw(envtree, ENV_AMPL, MAXDEPTH, 0, 0, scrn_w, scrn_h);*/
      objc_draw(envtree, ENV_ENV, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      setup_env(envtree[ENV_ENV].ob_spec.env);
   }
}

WORD env_button_delete(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   WORD p,anz,i;

   p=envtree[ENV_POINT].ob_spec.textedit->value;
   anz=envtree[ENV_ENV].ob_spec.env->points;
   if (p && p<anz-1)
   {
      anz--;
      for (i=p;i<max_points-1;i++)
      {
         envtree[ENV_ENV].ob_spec.env->time[i]=envtree[ENV_ENV].ob_spec.env->time[i+1];
         envtree[ENV_ENV].ob_spec.env->ampl[i]=envtree[ENV_ENV].ob_spec.env->ampl[i+1];
      }

      envtree[ENV_ENV].ob_spec.env->points=anz;
      envtree[ENV_POINT].ob_spec.textedit->max=anz-1;
      envtree[ENV_LOOP].ob_spec.textedit->max=anz-1;
      calc_envelope(envtree[ENV_ENV].ob_spec.env,1);
/*    objc_draw(envtree, ENV_TIME, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      objc_draw(envtree, ENV_AMPL, MAXDEPTH, 0, 0, scrn_w, scrn_h);*/
      objc_draw(envtree, ENV_ENV, MAXDEPTH, 0, 0, scrn_w, scrn_h);
      setup_env(envtree[ENV_ENV].ob_spec.env);
   }
}

VOID adjust_volume(OBJECT *tree,WORD obj,POPUPINFO *info)
{

   objc_outline(tree, NIL, obj);
   v_dark_tree(algtree);

   voltree[VOL_DELAY].ob_spec.slider->curr=curr_patch->delay;
   voltree[VOL_PAN].ob_spec.slider->curr=curr_patch->pan;
   voltree[VOL_VOL].ob_spec.slider->curr=curr_patch->volume&0xffff;

   objc_draw(voltree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   form_xdo(voltree, VOL_BAR);

   objc_draw(algtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   objc_outline(tree, obj, NIL);
}

VOID delay_change(OBJECT *tree,WORD obj,SLIDEINFO *info)
{
   curr_patch->delay=info->curr;
}

VOID pan_change(OBJECT *tree,WORD obj,SLIDEINFO *info)
{
   curr_patch->pan=info->curr;
}

VOID vol_change(OBJECT *tree,WORD obj,SLIDEINFO *info)
{
   curr_patch->volume=info->curr+(info->curr<<16);
}

WORD vol_button_ok(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   return -1;
}


int aktiv[64],akt_env_num;

VOID handle_choose(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   objc_outline(tree, NIL, obj);
   v_dark_tree(tree);
   akt_env_num=active_envelopes();

   auswtree[AUSW_SLIDER].ob_spec.slider->max=active_envelopes();
   auswtree[AUSW_SLIDER].ob_spec.slider->curr=active_envelopes();
   setup_chooser(0);
   objc_draw(auswtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   setup_chooser(0);
   form_xdo(auswtree, AUSW_BAR);

   objc_draw(envtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
   objc_outline(tree, obj, NIL);
}

VOID ausw_change(OBJECT *tree,WORD obj,SLIDEINFO *info)
{
   int i,sx,sy;

   setup_chooser(info->max-info->curr);
   for (i=AUSW_ENV1;i<=AUSW_ENV5;i++)
   {
      if (auswtree[i].ob_flags&HIDETREE)
      {
         vsf_color(LWHITE);
         objc_offset(auswtree,i,&sx,&sy);
         v_bar(sx,sy,auswtree[i].ob_width,auswtree[i].ob_height);
      }
      ob_draw(auswtree,i,0);
   }
}

VOID setup_chooser(WORD start)
{
   WORD i,o,nr;

   o=AUSW_ENV1;
   for (i=start;i<akt_env_num;i++)
   {
      nr=aktiv[i];
      auswtree[o].ob_spec.env->patch_env=(ENVPARA *)&env_table[dsp_envslots[nr].env_ix].dsp_addr;

      calc_envelope(auswtree[o].ob_spec.env,0);
      if (dsp_envslots[nr].start==org_work_addr)
         objc_outline(auswtree, o, NIL);
      else
         objc_outline(auswtree, NIL, o);

      auswtree[o].ob_flags&=~HIDETREE;
      o++;
      if (o>AUSW_ENV5)
         break;
   }

   if (o<AUSW_ENV5)
   {
      for (i=o;i<=AUSW_ENV5;i++)
      {
         objc_outline(auswtree, NIL, o);
         auswtree[i].ob_flags|=HIDETREE;
      }
   }
}


WORD choose_envelope(OBJECT *tree,WORD obj,WORD d1,WORD d2,WORD d3)
{
   int nr;

   temp2dspenv(2 * (envtree[ENV_ENV].ob_spec.env->points - 1),
             curr_patch->env[type].curr,
             curr_patch->env[type].release);

   nr=aktiv[auswtree[AUSW_SLIDER].ob_spec.slider->max-auswtree[AUSW_SLIDER].ob_spec.slider->curr];

   curr_patch->env[type].point=dsp_envslots[nr].start;

   org_work_addr=0L;
   if (dspenv2temp(curr_patch->env[type].point, type)!=FAILURE)
   {
      curr_patch->env[type].curr=env_table[dsp_envslots[nr].env_ix].start_value;
      curr_patch->env[type].release=env_table[dsp_envslots[nr].env_ix].release_slope;

      envtree[ENV_ENV].ob_spec.env->patch_env=&curr_patch->env[type];
      calc_envelope(envtree[ENV_ENV].ob_spec.env,0);
      setup_env(envtree[ENV_ENV].ob_spec.env);
   }
   return -1;
}


WORD active_envelopes(VOID)
{
   WORD i,c;

   c=0;
   for (i=0;i<64;i++)
      if (dsp_envslots[i].used)
      {
         aktiv[c]=i;
         c++;
      }

   return (c);
}



