/************************************************************************
 * TITLE:		  JAZ.C						*
 * PROJECT:	   JAGUAR/JAZ						*
 * FUNCTION:	  MAIN JAZ MODULE			 		*
 * PROGRAMMER:	  Hans-Martin Krober, Andreas Binner  			*
 * DATE:	   5/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"



char            ROM_VERSION[] = {"V0.92b "};
char            VERSION[40];

/*
 * ---------------------------------------------------------------- 
 * EXTERNALS
 */

EXTERN WORD     scrn_w, scrn_h;
EXTERN struct _pitchpatch pitchpatch[];

EXTERN BYTE     filebuf[];

EXTERN BYTE    *patchnameslist;
EXTERN BYTE    *samplenameslist;

EXTERN BYTE     SLASH;

EXTERN WORD     sprintf(BYTE *,...);
EXTERN VOID     read_cnf(VOID);
EXTERN VOID     set_delay(OBJECT *, WORD, POPUPINFO *);
EXTERN VOID     set_pitchbend(OBJECT *, WORD, POPUPINFO *);
EXTERN VOID     init_patches(VOID);
EXTERN VOID     pstab_handler(OBJECT *, WORD, WORD, WORD, ULONG);
EXTERN VOID     pstab_pload(OBJECT *, WORD, WORD, WORD, ULONG);
EXTERN VOID     pstab_psave(OBJECT *, WORD, WORD, WORD, ULONG);
EXTERN VOID     pstab_pview(OBJECT *, WORD, WORD, WORD, ULONG);
EXTERN VOID     pstab_pnew(OBJECT *, WORD, WORD, WORD, ULONG);
EXTERN VOID     pstab_pdelete(OBJECT *, WORD, WORD, WORD, ULONG);
EXTERN WORD     build_pedit(VOID);
EXTERN ULONG    patchtab[];	/* buffer for patches	 */
EXTERN BYTE     patch_names[][16];
EXTERN PATCHINFO patchinfo_table[];
EXTERN WORD     patch_cnt;
EXTERN WORD     sound_off;
EXTERN WORD     sound_off_cnt;
EXTERN LONG	sclock;
/*
 * ---------------------------------------------------------------- 
 * GLOBALS
 */

OBJECT          maintree[20];	/* Main Screen Objs */
OBJECT          jaztree[25];	/* PMT list Objs	 */
OBJECT          ptttree[25];	/* PMT Dialog Box */
OBJECT          pstabtree[25];	/* Patch	 Tables	Dialog Box */
OBJECT          rentree[10];	/* Rename Patch	Dialog Box */
OBJECT          filtertree[15];
OBJECT          globaltree[15];


BYTE           *pttlist[LIST_COLS * MAX_PTT];	/* PTT String List for dialog
						 * box */
PTT_TAB         ptt_table[MAX_PTT];	/* PTT Data */
WORD            ptt_count;	/* # of entries in	PTT	 */
WORD            ptt_id;		/* unique id for each entry */
LONG           *curr_patch;
WORD            curr_pnr;
WORD            curr_ptt;
LONG            effect_channel;
BYTE            jaz_prf_file[256];
WORD            _debug;
WORD            pmt_open;
WORD            pmt_omni_mode;
WORD            gl_effect;
WORD            gl_pitchbend;
LONG            midi_filter;	/* Bit  0: Program change 1: Pan 2: Volume 3:
				 * Pitchbend 4: Modulation */

WORD            ptt_addmode;

/*
 * ----------------------------------------------------------------
 * PROTOTYPES
 */
VOID            jazmain(VOID);
VOID            InitGEMObjs(VOID);
VOID            InitPttTable(VOID);
VOID            PttTable2Strings(WORD);
VOID            PttTable2PitchPatch(VOID);
VOID            pttlist_handler(OBJECT *, WORD, LISTINFO *);
VOID            pttlist_scrolled(OBJECT *, WORD, LISTINFO *);
LONG            pttbttn_handler(OBJECT *, WORD, WORD, WORD, ULONG);
WORD            pttcmp(PTT_TAB *, PTT_TAB *);
VOID            load_handler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            midi_handler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            global_handler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            midi_change_all(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3);
VOID            load_pmthandler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            save_handler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            save_pmthandler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            pstab_handler(OBJECT *, WORD, WORD, WORD, ULONG);
LONG            pstab_close(OBJECT *, WORD, WORD, WORD, ULONG);
WORD            write_pmp(BYTE *);
WORD            read_pmp(BYTE *);
VOID            change_surround(OBJECT *, WORD, SLINTINFO *);
VOID            change_tune(OBJECT *, WORD, SLIDEINFO *);
VOID            change_patch(OBJECT *, WORD, SLIDEINFO *);
VOID            change_volume(OBJECT * tree, WORD obj, SLIDEINFO * info);
VOID            change_channel(OBJECT * tree, WORD obj, SLIDEINFO * info);
VOID            midi_onoff(OBJECT * tree, WORD obj, WORD e, WORD, WORD);
VOID            scrn_onoff(OBJECT * tree, WORD obj, WORD e, WORD, WORD);
WORD            return_handler(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3);
VOID            handle_pmtlist(VOID);
VOID            pttlist_bthandler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            hog_handler(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            pstab_prename(OBJECT *, WORD, WORD, WORD, ULONG);
LONG            pmt_omni(OBJECT *, WORD, WORD, WORD, ULONG);

/*
 * ---------------------------------------------------------------- FUNCTIONS
 */


/*
 * C ENTRY POINT MAIN()
 */

VOID
jazmain(VOID)
{
	_debug = 0;
	gl_effect = 0;
	gl_pitchbend = 12;
	midi_filter = 0L;
	sound_off = 0;
	sound_off_cnt = 0;
	pmt_omni_mode = 0;
	sclock = 19;		/* default 20,77k */

	strcpy(VERSION, ROM_VERSION);
	strcat(VERSION, __DATE__);

	strcpy(jaz_prf_file, "jaz.prf");

	read_cnf();		/* read JAZ.CNF */
	init_synth();
	_init_midi();
	init_parse();
	
	appl_init();		/* init GEM library */
	_init_alert();
	init_patches();		/* copy default patches to patch table */
	InitPttTable();		/* Init PTT (Map) */
	PttTable2Strings(-1);
	InitGEMObjs();		/* Init GEM Object Trees */
	init_fsel();		/* Init File Selector */
#if 0
	build_pedit();		/* build Patch	Edit screens */
#endif
	build_jazalg();		/* build JAZ algorithm page	 */
	build_jazosc();		/* build JAZ osc page */
	build_jazenv();		/* build JAZ env page */
	pmt_open = FALSE;

	/*
	 * Read default performance file
	 */
	read_patch(PERF_FILE, jaz_prf_file, 0);

	objc_draw(maintree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	enable_sound();
	form_xdo(maintree, MAIN_BAR);
}

VOID
handle_pmtlist(VOID)
{
	jaztree[JAZ_TLOMNI].ob_state &= ~SELECTED;
	pmt_omni_mode = FALSE;
	objc_draw(jaztree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	pmt_open = TRUE;
	form_xdo(jaztree, JAZ_FILEBAR);
	pmt_open = FALSE;
	pmt_omni_mode = FALSE;

	v_draw_title();
	objc_draw(maintree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(maintree, MAIN_BAR, NIL);
}

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

/*
 * Init	Patch Translation Table
 */

VOID
InitPttTable()
{
	REG WORD        i;

	ptt_id = 0;
	for (i = 0; i < MIDI_CHANNELS; i++, ptt_id++) {
		ptt_table[i].act = 0;
		ptt_table[i].channel = i + 1;
		ptt_table[i].patch = 1;	/* default to patch 1 */
		ptt_table[i].start = 0;
		ptt_table[i].end = 127;
		ptt_table[i].offset = 0;
		ptt_table[i].priority = 7;
		ptt_table[i].volume = 127;
		ptt_table[i].tuning = 0x1000L;
		ptt_table[i].id = ptt_id;
#if 0
		ptt_table[i].ix = i;
		ptt_table[i].iix = 0;
#endif
		pitchpatch[i].translate = TRUE;
		pitchpatch[i].n = 1;
		pitchpatch[i].patch[0] = 0;
		pitchpatch[i].start[0] = 0;
		pitchpatch[i].end[0] = 127;
		pitchpatch[i].offset[0] = 0;
		pitchpatch[i].priority[0] = 7;
#if 0
		pitchpatch[i].ix[0] = ptt_id;
#endif

	}
#if 0
	ptt_table[14].patch = ptt_table[15].patch = 13;	/* for now */
	pitchpatch[14].patch[0] = pitchpatch[15].patch[0] = 13;
#endif
	ptt_count = 16;
}

/*
 * Convert Patch translation table values (which we	see	on the
 * screen) to PitchPatchTable used by the real-time	MIDI parser.
 */

VOID
PttTable2PitchPatch()
{
	REG PTT_TAB    *p;
	REG WORD        i, k, j, n;

	p = ptt_table;
	k = ptt_count;

	/*
	 * Reinitialize Table
	 */
	for (i = 0; i < MIDI_CHANNELS; i++) {
		pitchpatch[i].translate = FALSE;
		pitchpatch[i].n = 0;
	}

	/*
	 * Convert data
	 */
	for (i = 0; i < k; i++, p++) {
		/*
		 * The following 'if'	statement is for us to be on	the
		 * safe side. Because it could	be that a patch should be
		 * active but was refused to being active due to lack of DSP
		 * memory!
		 */
		if (patchinfo_table[p->patch - 1].active) {
			j = p->channel - 1;
			pitchpatch[j].translate = TRUE;
			n = pitchpatch[j].n++;
			pitchpatch[j].patch[n] = p->patch - 1;
			pitchpatch[j].start[n] = p->start;
			pitchpatch[j].end[n] = p->end;
			pitchpatch[j].offset[n] = p->offset;
			pitchpatch[j].priority[n] = p->priority;
#if 0
			pitchpatch[j].ix[n] = i;
#endif
			pitchpatch[j].cover[n] = FALSE;
		}
	}

	/*
	 * Set the other channels to the first patch, so that we don't crash!
	 * 
	 * N O T E :	We should let it point to a DEFAULT PATCH which
	 * !!!!!!!	is always there!!!!!!
	 */
	p = ptt_table;
#if 0
	for (i = 0; i < MIDI_CHANNELS; i++) {
		if (pitchpatch[i].translate == FALSE) {
			pitchpatch[i].translate = TRUE;
			pitchpatch[i].n = 1;
			pitchpatch[i].patch[0] = p->patch - 1;
			pitchpatch[i].start[0] = 0;
			pitchpatch[i].end[0] = 127;
			pitchpatch[i].offset[0] = 0;
			pitchpatch[i].ix[0] = 0;
		}
	}
#else
	/*
	 * We go even one step father: to cover the whole note range we add
	 * one whole note range pointing to patch # to the end. Since it's
	 * the end, the others have priority
	 */
	for (i = 0; i < MIDI_CHANNELS; i++) {
		pitchpatch[i].translate = TRUE;
		n = pitchpatch[i].n++;
		pitchpatch[i].patch[n] = 0;
		pitchpatch[i].start[n] = 0;
		pitchpatch[i].end[n] = 127;
		pitchpatch[i].offset[n] = 0;
		pitchpatch[i].cover[n] = TRUE;
	}

#endif


	/*
	 * debugging
	 */
	if (_debug) {
		BYTE            dbuf[80];
		for (i = 0; i < MIDI_CHANNELS; i++) {

			for (j = 0; j < pitchpatch[i].n; j++) {
				sprintf(dbuf, "ch=%02d p=%03d s=%03d e=%03d o=%03d",
					i + 1, pitchpatch[i].patch[j] + 1,
					pitchpatch[i].start[j],
					pitchpatch[i].end[j],
					pitchpatch[i].offset[j]);
				dos_echo(dbuf);
			}
		}
	}
}

/*
 * Convert Patch translation table values to strings
 */

VOID
PttTable2Strings(x)
	WORD            x;	/* either the index or if -1, do all */
{
	REG BYTE      **s;
	REG PTT_TAB    *p;
	REG WORD        i, k;

	if (x == -1) {
		s = pttlist;
		p = ptt_table;
		k = ptt_count;
	} else {
		s = &pttlist[x * LIST_COLS];
		p = &ptt_table[x];
		k = 1;
	}
	for (i = 0; i < k; i++, p++) {
		sprintf(p->s_act, "%c", (p->act == 0) ? ' ' : 'X');
		*s++ = p->s_act;
		sprintf(p->s_channel, "%02d", p->channel);
		*s++ = p->s_channel;
#if 0
		sprintf(p->s_patch, "%03d", p->patch);
#else
		p->s_patch = patch_names[p->patch - 1];
#endif
		*s++ = p->s_patch;
		sprintf(p->s_note, "%03d - %03d", p->start, p->end);
		*s++ = p->s_note;
		sprintf(p->s_offset, "%d", p->offset);
		*s++ = p->s_offset;
		sprintf(p->s_priority, "%d", p->priority);
		*s++ = p->s_priority;
		sprintf(p->s_volume, "%03d", p->volume);
		*s++ = p->s_volume;
		sprintf(p->s_tuning, "$%04lx", p->tuning);
		*s++ = p->s_tuning;
	}
}

/*
 * Build the GEM object	for	the	main page
 */

VOID
InitGEMObjs()
{
	LISTINFO       *list;

	objc_xadd(globaltree, NIL, GLOBAL_BOX,
		  G_BOX, -1, -1,
		  117, 10, 150, 124,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(globaltree, GLOBAL_BOX, GLOBAL_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 112, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, GLOBAL_BOX, 6,
		  T_OB_RATTACH, GLOBAL_BOX, 6,
		  T_OB_UATTACH, GLOBAL_BOX, 2,
		  T_BX_TEXT, "GLOBAL SETTINGS",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(globaltree, GLOBAL_BOX, GLOBAL_EFFECT,
		  G_XPOPUP, -1, -1,
		  6, 0, 130, 24,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, GLOBAL_TITLE, 10,
		  T_OB_DOWN, GLOBAL_PITCHBEND,
		  T_OB_UP, GLOBAL_BAR,
		  T_POP_SLNAME, "EFFECT",
		  T_POP_DATA, "None|Delay|(Reverb)|Surround",
		  T_POP_FONTID, FNT_MEDIUM,
		  T_POP_CALLBK, set_delay,
		  0);
	globaltree[GLOBAL_EFFECT].ob_spec.popup->index = gl_effect;

	objc_xadd(globaltree, GLOBAL_BOX, GLOBAL_PITCHBEND,
		  G_XPOPUP, -1, -1,
		  6, 0, 130, 24,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, GLOBAL_EFFECT, 8,
		  T_OB_DOWN, GLOBAL_BAR,
		  T_OB_UP, GLOBAL_EFFECT,
		  T_POP_SLNAME, "PITCH BEND",
		  T_POP_DATA, " +/- 12 | +/- 2 ",
		  T_POP_FONTID, FNT_MEDIUM,
		  T_POP_CALLBK, set_pitchbend,
		  0);
	globaltree[GLOBAL_PITCHBEND].ob_spec.popup->index = 
		(gl_pitchbend == 2) ? 1 : 0;

	objc_xadd(globaltree, GLOBAL_BOX, GLOBAL_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, GLOBAL_PITCHBEND,
		  T_OB_DATTACH, GLOBAL_BOX, 2,
		  T_OB_LATTACH, GLOBAL_BOX, 6,
		  T_OB_RATTACH, GLOBAL_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(globaltree, GLOBAL_BAR, GLOBAL_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, pstab_close,
		  T_OB_LATTACH, GLOBAL_BAR, 20,
		  T_OB_RATTACH, GLOBAL_BAR, 20,
		  T_OB_UATTACH, GLOBAL_BAR, 1,
		  0);



	objc_xadd(filtertree, NIL, MIDI_BOX,
		  G_BOX, -1, -1,
		  117, 30, 150, 140,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(filtertree, MIDI_BOX, MIDI_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 112, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, MIDI_BOX, 6,
		  T_OB_RATTACH, MIDI_BOX, 6,
		  T_OB_UATTACH, MIDI_BOX, 2,
		  T_BX_TEXT, "FILTER MIDI EVENTS",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(filtertree, MIDI_BOX, MIDI_PRGCHANGE,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, MIDI_TITLE, 10,
		  T_OB_DOWN, MIDI_PAN,
		  T_BT_TEXT, "PROGRAM CHANGE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	if (midi_filter & 1)
		filtertree[MIDI_PRGCHANGE].ob_state |= SELECTED;

	objc_xadd(filtertree, MIDI_BOX, MIDI_PAN,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, MIDI_PRGCHANGE, 8,
		  T_OB_UP, MIDI_PRGCHANGE,
		  T_OB_DOWN, MIDI_VOLUME,
		  T_BT_TEXT, "PAN",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	if (midi_filter & 2)
		filtertree[MIDI_PAN].ob_state |= SELECTED;

	objc_xadd(filtertree, MIDI_BOX, MIDI_VOLUME,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, MIDI_PAN, 8,
		  T_OB_UP, MIDI_PAN,
		  T_OB_DOWN, MIDI_PITCH,
		  T_BT_TEXT, "VOLUME",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	if (midi_filter & 4)
		filtertree[MIDI_VOLUME].ob_state |= SELECTED;

	objc_xadd(filtertree, MIDI_BOX, MIDI_PITCH,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, MIDI_VOLUME, 8,
		  T_OB_UP, MIDI_VOLUME,
		  T_OB_DOWN, MIDI_MODUL,
		  T_BT_TEXT, "PITCHBEND",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	if (midi_filter & 8)
		filtertree[MIDI_PITCH].ob_state |= SELECTED;

	objc_xadd(filtertree, MIDI_BOX, MIDI_MODUL,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, NORMAL,
		  T_OB_UATTACH, MIDI_PITCH, 8,
		  T_OB_UP, MIDI_PITCH,
		  T_OB_DOWN, MIDI_BAR,
		  T_BT_TEXT, "MODULATION",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	if (midi_filter & 16)
		filtertree[MIDI_MODUL].ob_state |= SELECTED;

	objc_xadd(filtertree, MIDI_BOX, MIDI_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, MIDI_MODUL,
		  T_OB_UATTACH, MIDI_MODUL, 8,
		  T_OB_LATTACH, MIDI_BOX, 6,
		  T_OB_RATTACH, MIDI_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(filtertree, MIDI_BAR, MIDI_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, pstab_close,
		  T_OB_LATTACH, MIDI_BAR, 20,
		  T_OB_RATTACH, MIDI_BAR, 20,
		  T_OB_UATTACH, MIDI_BAR, 1,
		  0);


	objc_xadd(rentree, NIL, RENAME_BOX,
		  G_BOX, -1, -1,
		  92, 20, 184, 90,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(rentree, RENAME_BOX, RENAME_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 112, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, RENAME_BOX, 6,
		  T_OB_RATTACH, RENAME_BOX, 6,
		  T_OB_UATTACH, RENAME_BOX, 2,
		  T_BX_TEXT, "RENAME PATCH",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);

	objc_xadd(rentree, RENAME_BOX, RENAME_NAME,
		  G_XTEXTEDIT, -1, -1,
		  0, 0, 104, 24,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, RENAME_BOX, 4,
		  T_OB_RATTACH, RENAME_BOX, 4,
		  T_OB_UATTACH, RENAME_TITLE, 8,
		  T_OB_DOWN, RENAME_BAR,
		  T_EDIT_NAME, "NAME",
		  T_EDIT_FONTID, 1,
		  T_EDIT_MAXSIZE, 16,
		  T_EDIT_DATA, "01234567890123456",
		  0);

	objc_xadd(rentree, RENAME_BOX, RENAME_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, RENAME_NAME,
		  T_OB_UATTACH, RENAME_NAME, 6,
		  T_OB_LATTACH, RENAME_BOX, 6,
		  T_OB_RATTACH, RENAME_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(rentree, RENAME_BAR, RENAME_CLOSE,
		  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, pstab_close,
		  T_OB_LATTACH, RENAME_BAR, 20,
		  T_OB_RATTACH, RENAME_BAR, 20,
		  T_OB_UATTACH, RENAME_BAR, 1,
		  0);


	objc_xadd(maintree, NIL, MAIN_BOX,
		  G_IBOX, -1, -1,
		  0, 0, scrn_w, scrn_h,
		  IS3DOBJ | NONE, NORMAL,
		  0);

	objc_xadd(maintree, MAIN_BOX, MAIN_BAR,
		  G_XBAR, -1, -1,
		  218, 90, 150, 107,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_BA_NUM, 7,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(maintree, MAIN_BAR, MAIN_EDITPMT,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "EDIT PATCH MAP TABLE",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '1',
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_BAR, 2,
		  T_BT_CALLBK, handle_pmtlist,
		  0);
	objc_xadd(maintree, MAIN_BAR, MAIN_EDITPATCHES,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "EDIT PATCHES",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '2',
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_EDITPMT, 2,
		  T_BT_CALLBK, pstab_handler,
		  0);
	objc_xadd(maintree, MAIN_BAR, MAIN_LOADPRF,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "LOAD PERFORMANCE FILE",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, load_handler,
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_EDITPATCHES, 2,
		  0);

	objc_xadd(maintree, MAIN_BAR, MAIN_SAVEPRF,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "SAVE PERFORMANCE FILE",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, save_handler,
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_LOADPRF, 2,
		  0);

	objc_xadd(maintree, MAIN_BAR, MAIN_MIDI,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "MIDI SETUP",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '5',
		  T_BT_CALLBK, midi_handler,
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_SAVEPRF, 2,
		  0);

	objc_xadd(maintree, MAIN_BAR, MAIN_GLOBAL,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "GLOBAL SETTINGS",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '6',
		  T_BT_CALLBK, global_handler,
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_MIDI, 2,
		  0);

	objc_xadd(maintree, MAIN_BAR, MAIN_BUSHOG,
		  G_XBUTTON, -1, -1,
		  0, 2, 145, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "BUS HOG",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '7',
		  T_OB_LATTACH, MAIN_BAR, 1,
		  T_OB_UATTACH, MAIN_GLOBAL, 2,
		  T_BT_CALLBK, hog_handler,
		  0);
	objc_xadd(maintree, MAIN_BAR, MAIN_VERSION,
		  G_XTEXT, -1, -1,
		  0, 2, 145, 8,
		  NONE, NORMAL,
		  T_OB_LATTACH, MAIN_BAR, 2,
		  T_OB_UATTACH, MAIN_BUSHOG, 4,
		  T_BX_TEXT, VERSION,
		  T_BX_BGCOLOR, 0,
		  T_BX_TXTCOLOR, 1,
		  T_BX_FONTID, 0,
		  T_BX_ALIGN, TE_CNTR,
		  0);



	objc_xadd(jaztree, NIL, JAZ_BOX,
		  G_BOX, -1, -1,
		  2, 2, scrn_w - 4, scrn_h - 4,
		  IS3DOBJ | NONE, NORMAL,
		  0);


	objc_xadd(jaztree, JAZ_BOX, JAZ_TLBOX,
		  G_XBAR, -1, -1,
		  0, 0, 0, 24,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_UATTACH, JAZ_BOX, 2,
		  T_OB_LATTACH, JAZ_BOX, 4,
		  T_OB_RATTACH, JAZ_BOX, 4,
		  0);
	objc_xadd(jaztree, JAZ_TLBOX, JAZ_TLTEXT,
		  G_XTEXT, -1, -1,
		  0, 0, 0, 6,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_UATTACH, JAZ_TLBOX, 0,
		  T_OB_LATTACH, JAZ_TLBOX, 4,
		  T_OB_RATTACH, JAZ_TLBOX, 4,
		  T_BX_TEXT, STR_TIMELEFT,
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(jaztree, JAZ_TLBOX, JAZ_TLSLIDER,
		  G_XBAR, -1, -1,
		  0, 0, 112, 8,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_UATTACH, JAZ_TLTEXT, 0,
		  T_OB_LATTACH, JAZ_TLBOX, 5,
		  0);
	objc_xadd(jaztree, JAZ_TLBOX, JAZ_TLVOICES,
		  G_XBAR, -1, -1,
		  0, 0, 112, 8,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_UATTACH, JAZ_TLTEXT, 0,
		  T_OB_LATTACH, JAZ_TLSLIDER, 5,
		  0);
	objc_xadd(jaztree, JAZ_TLBOX, JAZ_TLOMNI,
		  G_XBUTTON, -1, -1,
		  0, 0, 112, 8,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, JAZ_TLTEXT, 3,
		  T_OB_LATTACH, JAZ_TLVOICES, 7,
		  T_OB_DOWN, JAZ_PTTBOX,
		  T_BT_TEXT, "OMNI MODE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, pmt_omni,
		  0);

	objc_xadd(jaztree, JAZ_BOX, JAZ_PTTBOX,
		  G_XLIST, -1, -1,
		  4, 36, 372, 130,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UP, JAZ_TLOMNI,
		  T_OB_DOWN, JAZ_FILEBAR,
		  T_LST_NAME, STR_PTT,
		  T_LST_TITLES, STR_ACT,
		  T_LST_TITLES, STR_CHANNEL,
		  T_LST_TITLES, STR_PATCH,
		  T_LST_TITLES, STR_NOTERANGE,
		  T_LST_TITLES, STR_OFFSET,
		  T_LST_TITLES, STR_PRIORITY,
		  T_LST_TITLES, STR_VOL,
		  T_LST_TITLES, STR_TUNING,
		  T_LST_CALLBK, pttlist_handler,
		  T_LST_SCROLLED, pttlist_scrolled,
		  0);
	list = jaztree[JAZ_PTTBOX].ob_spec.list;
	list->data = (VOID *) & pttlist;
	list->index = 0;
	list->maxitems = ptt_count;

	objc_xadd(jaztree, JAZ_BOX, JAZ_FILEBAR,
		  G_XBAR, -1, -1,
		  4, 0, 372, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, JAZ_PTTBOX,
		  T_OB_UATTACH, JAZ_PTTBOX, 3,
		  T_BA_NUM, 4,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(jaztree, JAZ_FILEBAR, JAZ_PAGE,
		  G_XBUTTON, -1, -1,
		  0, 2, 80, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Edit",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_OB_LATTACH, JAZ_FILEBAR, 6,
		  T_OB_UATTACH, JAZ_FILEBAR, 1,
		  T_BT_CALLBK, pttlist_bthandler,
		  0);
	objc_xadd(jaztree, JAZ_FILEBAR, JAZ_LOAD,
		  G_XBUTTON, -1, -1,
		  0, 2, 80, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Load PMT",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, load_pmthandler,
		  T_OB_LATTACH, JAZ_PAGE, 6,
		  T_OB_UATTACH, JAZ_FILEBAR, 1,
		  0);
	objc_xadd(jaztree, JAZ_FILEBAR, JAZ_SAVE,
		  G_XBUTTON, -1, -1,
		  0, 2, 80, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, STR_SAVEPTT,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, save_pmthandler,
		  T_OB_LATTACH, JAZ_LOAD, 6,
		  T_OB_UATTACH, JAZ_FILEBAR, 1,
		  0);
	objc_xadd(jaztree, JAZ_FILEBAR, JAZ_CLOSE,
		  G_XBUTTON, -1, -1,
		  0, 2, 80, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Close",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, return_handler,
		  T_OB_LATTACH, JAZ_SAVE, 6,
		  T_OB_UATTACH, JAZ_FILEBAR, 1,
		  0);

	/************************/
	/* Patch Mapping Tree	 */
	/************************/

	objc_xadd(ptttree, NIL, PTT_BOX,
		  G_BOX, -1, -1,
		  10, 30, 360, 160,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(ptttree, PTT_BOX, PTT_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0,
		  FNT_MSTRWIDTH(STR_PTTTITLE) + 16, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, PTT_BOX, 6,
		  T_OB_RATTACH, PTT_BOX, 6,
		  T_OB_UATTACH, PTT_BOX, 2,
		  T_BX_TEXT, STR_PTTTITLE,
		  T_BX_FONTID, FNT_MEDIUM,
		  T_BX_ALIGN, TE_CNTR,
		  0);

	objc_xadd(ptttree, PTT_BOX, PTT_FRAME1,
		  G_BOX, -1, -1,
		  6, 22, 165, 110,
		  FRAME, NORMAL,
		  0);

	objc_xadd(ptttree, PTT_FRAME1, PTT_CHANNEL,
		  G_XREALSLIDER, -1, -1,
		  8, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_FINE,
		  T_OB_RIGHT, PTT_PATCH,
		  T_SLIDE_SLNAME, "CHAN",
		  T_SLIDE_MIN, 1L,
		  T_SLIDE_MAX, 16L,
		  T_SLIDE_CALLBK, change_channel,
		  0);

	objc_xadd(ptttree, PTT_FRAME1, PTT_PATCH,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_CHANNEL, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_CHANNEL,
		  T_OB_RIGHT, PTT_START,
		  T_SLIDE_SLNAME, STR_PTTPATCH,
		  T_SLIDE_MIN, 1L,
		  T_SLIDE_MAX, 128L,
		  T_SLIDE_CALLBK, change_patch,
		  0);

	objc_xadd(ptttree, PTT_FRAME1, PTT_START,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_PATCH, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_PATCH,
		  T_OB_RIGHT, PTT_END,
		  T_SLIDE_SLNAME, STR_PTTSTART,
		  T_SLIDE_MAX, 127L,
		  0);

	objc_xadd(ptttree, PTT_FRAME1, PTT_END,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_START, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_START,
		  T_OB_RIGHT, PTT_OFFSET,
		  T_SLIDE_SLNAME, STR_PTTEND,
		  T_SLIDE_MAX, 127L,
		  0);

	objc_xadd(ptttree, PTT_FRAME1, PTT_OFFSET,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_END, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_END,
		  T_OB_RIGHT, PTT_VOLUME,
		  T_SLIDE_SLNAME, STR_PTTOFFSET,
		  T_SLIDE_MAX, 127L,
		  0);

	objc_xadd(ptttree, PTT_BOX, PTT_FRAME2,
		  G_BOX, -1, -1,
		  177, 22, 175, 110,
		  FRAME, NORMAL,
		  0);


	objc_xadd(ptttree, PTT_FRAME2, PTT_VOLUME,
		  G_XREALSLIDER, -1, -1,
		  8, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_OFFSET,
		  T_OB_RIGHT, PTT_PRIORITY,
		  T_SLIDE_SLNAME, STR_PTTVOLUME,
		  T_SLIDE_MAX, 127L,
		  T_SLIDE_CALLBK, change_volume,
		  0);

	objc_xadd(ptttree, PTT_FRAME2, PTT_PRIORITY,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_VOLUME, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_VOLUME,
		  T_OB_RIGHT, PTT_OCTAVE,
		  T_SLIDE_SLNAME, STR_PTTPRIORITY,
		  T_SLIDE_MAX, 7L,
		  0);

	objc_xadd(ptttree, PTT_FRAME2, PTT_OCTAVE,
		  G_XREALSLIDER, -1, -1,
		  0, 16, 25, 86,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_PRIORITY, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_PRIORITY,
		  T_OB_RIGHT, PTT_HALFSTEP,
		  T_SLIDE_SLNAME, "OCT",
		  T_SLIDE_MAX, 3L,
		  T_SLIDE_MIN, -3L,
		  T_SLIDE_CALLBK, change_tune,
		  0);

	objc_xadd(ptttree, PTT_FRAME2, PTT_HALFSTEP,
		  G_XREALSLIDER, -1, -1,
		  0, 16, 25, 86,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_OCTAVE, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_OCTAVE,
		  T_OB_RIGHT, PTT_FINE,
		  T_SLIDE_SLNAME, "HALF",
		  T_SLIDE_MAX, 11L,
		  T_SLIDE_CALLBK, change_tune,
		  0);
	objc_xadd(ptttree, PTT_FRAME2, PTT_FINE,
		  G_XREALSLIDER, -1, -1,
		  0, 16, 25, 86,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PTT_HALFSTEP, 6,
		  T_OB_UP, PTT_BAR,
		  T_OB_DOWN, PTT_BAR,
		  T_OB_LEFT, PTT_HALFSTEP,
		  T_OB_RIGHT, PTT_CHANNEL,
		  T_SLIDE_SLNAME, "FINE",
		  T_SLIDE_MAX, 243L,
		  T_SLIDE_CALLBK, change_tune,
		  0);

	objc_xadd(ptttree, PTT_FRAME2, PTT_TUNING,
		  G_XBOXTEXT, -1, -1,
		  0, 4, 75, 7,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, PTT_PRIORITY, 6,
		  T_BX_TEXT, "TUNING",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);


	objc_xadd(ptttree, PTT_BOX, PTT_BAR,
		  G_XBAR, -1, -1,
		  4, 0, 372, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_DOWN, PTT_CHANNEL,
		  T_OB_UP, PTT_VOLUME,
		  T_OB_UATTACH, PTT_FRAME2, 2,
		  T_OB_LATTACH, PTT_BOX, 6,
		  T_OB_RATTACH, PTT_BOX, 6,
		  T_BA_NUM, 4,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(ptttree, PTT_BAR, PTT_CHANGE,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, STR_CHANGE,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, pttbttn_handler,
		  T_OB_LATTACH, PTT_BAR, 6,
		  T_OB_UATTACH, PTT_BAR, 1,
		  0);
	objc_xadd(ptttree, PTT_BAR, PTT_ADD,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, STR_ADD,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, pttbttn_handler,
		  T_OB_LATTACH, PTT_CHANGE, 6,
		  T_OB_UATTACH, PTT_BAR, 1,
		  0);
	objc_xadd(ptttree, PTT_BAR, PTT_DELETE,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, STR_DELETE,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, pttbttn_handler,
		  T_OB_LATTACH, PTT_ADD, 6,
		  T_OB_UATTACH, PTT_BAR, 1,
		  0);
	objc_xadd(ptttree, PTT_BAR, PTT_CANCEL,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, STR_CANCEL,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, pttbttn_handler,
		  T_OB_RATTACH, PTT_BAR, 6,
		  T_OB_UATTACH, PTT_BAR, 1,
		  0);
#if	1
	objc_xadd(pstabtree, NIL, PSTAB_BOX,
		  G_BOX, -1, -1,
	/* 0, 0, scrn_w, scrn_h, */
		  10, 6, 360, 188,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(pstabtree, PSTAB_BOX, PSTAB_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0,
		  FNT_MSTRWIDTH(STR_PSTABTITLE) + 16, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, PSTAB_BOX, 6,
		  T_OB_RATTACH, PSTAB_BOX, 6,
		  T_OB_UATTACH, PSTAB_BOX, 2,
		  T_BX_TEXT, STR_PSTABTITLE,
		  T_BX_FONTID, FNT_MEDIUM,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(pstabtree, PSTAB_BOX, PSTAB_PLIST,
		  G_XLIST, -1, -1,
		  0, 0, 334, 100,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_DOWN, PSTAB_PBAR,
		  T_OB_UP, PSTAB_MBAR,
		  T_OB_UATTACH, PSTAB_TITLE, 6,
		  T_OB_LATTACH, PSTAB_BOX, 12,
		  T_LST_NAME, STR_PSTABPATCHES,
		  T_LST_TITLES, STR_PSTABNR,
		  T_LST_TITLES, STR_PSTABNAME,
		  T_LST_TITLES, STR_PSTABTYPE,
		  T_LST_TITLES, STR_PSTABGROUP,
		  T_LST_TITLES, STR_PSTABACTI,
		  T_LST_CALLBK, pstab_pview,
		  0);
	list = pstabtree[PSTAB_PLIST].ob_spec.list;
	list->data = (VOID *) & patchnameslist;
	list->index = 0;
	list->maxitems = 128;

	objc_xadd(pstabtree, PSTAB_BOX, PSTAB_PBAR,
		  G_XBAR, -1, -1,
		  0, 0, 340, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_DOWN, PSTAB_MBAR,
		  T_OB_UP, PSTAB_PLIST,
		  T_OB_UATTACH, PSTAB_PLIST, 3,
		  T_OB_LATTACH, PSTAB_BOX, 9,
		  T_BA_NUM, 6,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(pstabtree, PSTAB_PBAR, PSTAB_PVIEW,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 10,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PSTAB_PBAR, 2,
		  T_OB_UATTACH, PSTAB_PBAR, 2,
		  T_BT_TEXT, STR_PSTABVIEW,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, pstab_pview,
		  0);
	objc_xadd(pstabtree, PSTAB_PBAR, PSTAB_PLOAD,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 10,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PSTAB_PVIEW, 3,
		  T_OB_UATTACH, PSTAB_PBAR, 2,
		  T_BT_TEXT, STR_PSTABLOAD,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, pstab_pload,
		  0);

	objc_xadd(pstabtree, PSTAB_PBAR, PSTAB_PSAVE,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 10,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PSTAB_PLOAD, 3,
		  T_OB_UATTACH, PSTAB_PBAR, 2,
		  T_BT_TEXT, STR_PSTABSAVE,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, pstab_psave,
		  0);

	objc_xadd(pstabtree, PSTAB_PBAR, PSTAB_PDELETE,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 10,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PSTAB_PSAVE, 3,
		  T_OB_UATTACH, PSTAB_PBAR, 2,
		  T_BT_TEXT, STR_PSTABDELETE,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, pstab_pdelete,
		  0);

	objc_xadd(pstabtree, PSTAB_PBAR, PSTAB_PNEW,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 10,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PSTAB_PDELETE, 3,
		  T_OB_UATTACH, PSTAB_PBAR, 2,
		  T_BT_TEXT, STR_PSTABNEW,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '5',
		  T_BT_CALLBK, pstab_pnew,

		  0);

	objc_xadd(pstabtree, PSTAB_PBAR, PSTAB_PRENAME,
		  G_XBUTTON, -1, -1,
		  0, 2, 50, 10,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_LATTACH, PSTAB_PNEW, 3,
		  T_OB_UATTACH, PSTAB_PBAR, 2,
		  T_BT_TEXT, STR_PSTABRENAME,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '6',
		  T_BT_CALLBK, pstab_prename,
		  0);

	objc_xadd(pstabtree, PSTAB_BOX, PSTAB_MBAR,
		  G_XBAR, -1, -1,
		  0, 0, 160, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_DOWN, PSTAB_PLIST,
		  T_OB_UP, PSTAB_PBAR,
		  T_OB_UATTACH, PSTAB_PBAR, 6,
		  T_OB_LATTACH, PSTAB_BOX, 6,
		  T_OB_RATTACH, PSTAB_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(pstabtree, PSTAB_MBAR, PSTAB_CLOSE,
		  G_XBUTTON, -1, -1,
		  0, 2, 60, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UATTACH, PSTAB_MBAR, 1,
		  T_OB_LATTACH, PSTAB_MBAR, 100,
		  T_OB_RATTACH, PSTAB_MBAR, 100,
		  T_BT_TEXT, STR_PSTABCLOSE,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, pstab_close,
		  0);

#endif
}

/*
 * Handle the PTT List - The 'A' (Select) Button was pressed inside	the
 * list.
 */

VOID
pttlist_bthandler(tree, obj, d1, d2, d3)
	OBJECT         *tree;
	WORD            obj;
	WORD            d1;
	WORD            d2;
	ULONG           d3;
{
	pttlist_handler(tree, obj, jaztree[JAZ_PTTBOX].ob_spec.list);
}

VOID
pttlist_handler(tree, obj, info)
	OBJECT         *tree;
	WORD            obj;
	LISTINFO       *info;
{
	LONG            tune, o, h, f;
	REG WORD        i, ch;
	BYTE            temp[255];
	LISTINFO       *list = jaztree[JAZ_PTTBOX].ob_spec.list;
	PTT_TAB        *p = &ptt_table[info->index];

	sprintf(temp, "Patch Mapping: '%s' to #%d", patch_names[p->patch - 1], p->channel);
	objc_xupdate(ptttree, PTT_TITLE, T_BX_TEXT, temp, 0);
	objc_xupdate(ptttree, PTT_CHANNEL, T_SLIDE_DEFAULT, (LONG) p->channel, 0);
	objc_xupdate(ptttree, PTT_PATCH, T_SLIDE_DEFAULT, (LONG) p->patch, 0);
	objc_xupdate(ptttree, PTT_PATCH, T_SLIDE_MAX, (LONG) patch_cnt, 0);
	objc_xupdate(ptttree, PTT_START, T_SLIDE_DEFAULT, (LONG) p->start, 0);
	objc_xupdate(ptttree, PTT_END, T_SLIDE_DEFAULT, (LONG) p->end, 0);
	objc_xupdate(ptttree, PTT_OFFSET, T_SLIDE_DEFAULT, (LONG) p->offset, 0);
	objc_xupdate(ptttree, PTT_PRIORITY, T_SLIDE_DEFAULT, (LONG) p->priority, 0);
	objc_xupdate(ptttree, PTT_VOLUME, T_SLIDE_DEFAULT, (LONG) p->volume, 0);

	tune = p->tuning;
	tune2ohf(tune, &o, &h, &f);

	objc_xupdate(ptttree, PTT_OCTAVE, T_SLIDE_DEFAULT, o, 0);
	objc_xupdate(ptttree, PTT_HALFSTEP, T_SLIDE_DEFAULT, h, 0);
	objc_xupdate(ptttree, PTT_FINE, T_SLIDE_DEFAULT, f, 0);

	/*
	 * find current line	in pitchpatch array
	 */
	ch = p->channel - 1;
	curr_ptt = -1;
	for (i = 0; i < pitchpatch[ch].n; i++) {
		if (pitchpatch[ch].cover[i])
			continue;
		if ((pitchpatch[ch].start[i] == p->start) &&
		    (pitchpatch[ch].end[i] == p->end)) {
			curr_ptt = i;
			break;
		}
	}
	ptt_addmode = 0;
	v_dark_tree(tree);
	objc_draw(ptttree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(ptttree, PTT_BAR);
	objc_draw(jaztree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, obj, NIL);
	if (ptt_addmode != 0) {
		if (list->index > ptt_addmode) {
			while (ptt_addmode != list->index) {
				list->index--;
				up_list(jaztree, JAZ_PTTBOX);
			}
		} else {
			while (list->index != ptt_addmode) {
				list->index++;
				dn_list(jaztree, JAZ_PTTBOX);
			}

		}
	}
}

/*
 * Handle the buttons in the PTT box (Add, Delete, Change, Cancel)
 */


LONG
pttbttn_handler(tree, obj, bttn, n, k)
	OBJECT         *tree;
	WORD            obj, bttn, n;
	ULONG           k;
{
	PTT_TAB        *p;
	WORD            x, ch;
	LONG            lvalue, o, h, f;
	WORD            sort;
	REG WORD        i, j, l;
	WORD            ix, iix;
	WORD            channel, start, end, patch;
	LISTINFO       *list = jaztree[JAZ_PTTBOX].ob_spec.list;
	WORD            over_start[32], over_end[32];



	objc_xget(ptttree, PTT_PATCH, T_SLIDE_DEFAULT, &lvalue, 0);
	patch = (WORD) (lvalue - 1L);

	if ((bttn == PTT_ADD) || (bttn == PTT_CHANGE)) {
		objc_xget(ptttree, PTT_CHANNEL, T_SLIDE_DEFAULT, &lvalue, 0);
		channel = (WORD) lvalue;
		objc_xget(ptttree, PTT_START, T_SLIDE_DEFAULT, &lvalue, 0);
		start = (WORD) lvalue;
		objc_xget(ptttree, PTT_END, T_SLIDE_DEFAULT, &lvalue, 0);
		end = (WORD) lvalue;

		if (start > end) {
			form_alert(FRM_ALERT, FMSTR_LESSTHAN);
			return 0L;	/* Don't close, continue with dialog */
		}
		ch = channel - 1;

		for (i = 0, j = 0, l = 0; i < pitchpatch[ch].n; i++) {
			if (pitchpatch[ch].cover[i] == TRUE)
				continue;
			if (i == curr_ptt)	/* don't check current line */
				continue;
			if
				((pitchpatch[ch].start[i] == start) ||
				 (pitchpatch[ch].end[i] == start) ||
				 ((pitchpatch[ch].start[i] <= start) &&
				  (start < pitchpatch[ch].end[i])))
				over_start[j++] = i;
			if
				((pitchpatch[ch].start[i] == end) ||
				 (pitchpatch[ch].end[i] == end) ||
				 ((pitchpatch[ch].start[i] < end) &&
				  (end <= pitchpatch[ch].end[i])))
				over_end[l++] = i;
		}

		if ((j > 0) || (l > 0)) {
			form_alert(FRM_ALERT, FMSTR_OVERLAP);
			return 0L;	/* Don't close, continue with dialog */
		}
	}
	ptt_addmode = 0;
	switch (bttn) {
	case PTT_ADD:
		if (ptt_count >= MAX_PTT) {
			form_alert(FRM_ALERT, FMSTR_TOOMANYPTT);
			return -1L;
		}
		x = ptt_count++;
		p = &ptt_table[x];
		sort = TRUE;
		ptt_addmode = 1;
		break;
	case PTT_CHANGE:
		p = &ptt_table[x = list->index];
		sort = FALSE;
		break;
	case PTT_DELETE:
		if (ptt_count <= 1) {
			form_alert(FRM_ALERT, FMSTR_CANTDELLASTPTT);
			return 0L;
		}
		x = list->index;
#if	0
		ix = ptt_table[x].ix;
		iix = ptt_table[x].iix;
#endif
		for (i = x; i < (ptt_count - 1); i++) {
			ptt_table[i] = ptt_table[i + 1];
		}
		list->maxitems = --ptt_count;
		if (list->index >= list->maxitems)
			list->index = list->maxitems - 1;
		if (list->index < 0)
			list->index = 0;

		for (i = 0; i < ptt_count; i++) {
			if ((ptt_table[i].patch - 1) == patch)
				break;
		}
		if (i == ptt_count)
			mk_one_patch_inactive(patch);

		PttTable2Strings(-1);
		PttTable2PitchPatch();	/* update	also MIDI parser
					 * table!! */


		update_patchnameslist();

		return -1L;
		break;
	case PTT_CANCEL:
		return -1L;
		break;
	default:
		return 0L;
	}
	if (patchinfo_table[patch].active == FALSE) {
		if (mk_one_patch_active(patch) == FAILURE) {
			if (bttn == PTT_ADD)
				ptt_count--;
			form_alert(FRM_ALERT, FMSTR_UNABLEMKPTCHACTIVE);
			return 0L;
		}
	}
	p->act = 0;

	p->start = start;
	p->end = end;
	p->channel = channel;

	objc_xget(ptttree, PTT_PATCH, T_SLIDE_DEFAULT, &lvalue, 0);
	patch = p->patch = (WORD) lvalue;
	objc_xget(ptttree, PTT_OFFSET, T_SLIDE_DEFAULT, &lvalue, 0);
	p->offset = (WORD) lvalue;
	objc_xget(ptttree, PTT_PRIORITY, T_SLIDE_DEFAULT, &lvalue, 0);
	p->priority = (WORD) lvalue;
	objc_xget(ptttree, PTT_VOLUME, T_SLIDE_DEFAULT, &lvalue, 0);
	p->volume = (WORD) lvalue;
	objc_xget(ptttree, PTT_OCTAVE, T_SLIDE_DEFAULT, &o, 0);
	objc_xget(ptttree, PTT_HALFSTEP, T_SLIDE_DEFAULT, &h, 0);
	objc_xget(ptttree, PTT_FINE, T_SLIDE_DEFAULT, &f, 0);

	p->tuning = ohf2tune(o, h, f);
	patchtab[21 * (p->patch - 1) + 3L] = p->tuning;

	if (sort) {
		qsort((BYTE *) ptt_table, ptt_count, (WORD) sizeof(PTT_TAB), &pttcmp);
		list->maxitems = ptt_count;
		PttTable2Strings(-1);
	} else
		PttTable2Strings(x);

	if (ptt_addmode) {
		for (i = 0; i < ptt_count; i++) {
			if ((patch == ptt_table[i].patch) &&
			    (channel == ptt_table[i].channel) &&
			    (start == ptt_table[i].start) &&
			    (end == ptt_table[i].end))
				break;
		}
		if (i != ptt_count)
			ptt_addmode = i;
		else
			ptt_addmode = 0;
	}
	PttTable2PitchPatch();	/* also,	update the MIDI	table */
	update_patchnameslist();

	return -1L;
}

/*
 * MIDI	Program	change event
 */
VOID
program_change(channel, patch)
	WORD            channel, patch;
{
	REG PTT_TAB    *p;
	REG WORD        i, j, x;
	LISTINFO       *list = jaztree[JAZ_PTTBOX].ob_spec.list;

	if (patch >= patch_cnt)
		return;

	for (i = 0; i < ptt_count; i++) {
		if (ptt_table[i].channel == (channel + 1)) {
			for (j = i; j < (ptt_count - 1); j++)
				ptt_table[j] = ptt_table[j + 1];
			ptt_count--;
		}
	}
	x = ptt_count++;
	p = &ptt_table[x];
	p->channel = channel + 1;
	p->patch = patch + 1;
	p->start = 0;
	p->end = 127;
	p->offset = 0;
	p->volume = 127;
	p->tuning = 0x1000;

	if (patchinfo_table[patch].active == FALSE) {
		if (mk_one_patch_active(patch) == FAILURE) {
			ptt_count--;
			form_alert(FRM_ALERT, FMSTR_UNABLEMKPTCHACTIVE);
			return;
		}
	}
	qsort((BYTE *) ptt_table, ptt_count, (WORD) sizeof(PTT_TAB), &pttcmp);

	list->maxitems = ptt_count;
	PttTable2Strings(-1);
	PttTable2PitchPatch();	/* also,	update the MIDI	table */
	update_patchnameslist();
	if (pmt_open)
		objc_draw(jaztree, JAZ_PTTBOX, MAXDEPTH, 0, 0, scrn_w, scrn_h);

}




VOID
midi_onoff(OBJECT * tree, WORD obj, WORD e, WORD d1, WORD d2)
{
	if (IsSelected(obj))
		midi_on();
	else
		midi_off();
}

VOID
scrn_onoff(OBJECT * tree, WORD obj, WORD e, WORD d1, WORD d2)
{
	if (IsSelected(obj))
		video_on();
	else
		video_off();
}

VOID
change_patch(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	LONG            o, h, f, v;
	BYTE            temp[255];

	tune2ohf(patchtab[21 * (info->curr - 1) + 3L], &o, &h, &f);
	v = (patchtab[21 * (info->curr - 1) + 20L] >> 8) & 0xff;

	sprintf(temp, "Patch Mapping: '%s' to #%d", patch_names[info->curr - 1], (WORD) ptttree[PTT_CHANNEL].ob_spec.slider->curr);
	objc_xupdate(ptttree, PTT_TITLE, T_BX_TEXT, temp, 0);
	objc_xupdate(ptttree, PTT_OCTAVE, T_SLIDE_DEFAULT, o, 0);
	objc_xupdate(ptttree, PTT_HALFSTEP, T_SLIDE_DEFAULT, h, 0);
	objc_xupdate(ptttree, PTT_FINE, T_SLIDE_DEFAULT, f, 0);
	objc_xupdate(ptttree, PTT_VOLUME, T_SLIDE_DEFAULT, v, 0);
	ob_draw(ptttree, PTT_TITLE, 0);
	ob_draw(ptttree, PTT_OCTAVE, 0);
	ob_draw(ptttree, PTT_HALFSTEP, 0);
	ob_draw(ptttree, PTT_FINE, 0);
	ob_draw(ptttree, PTT_VOLUME, 0);
}

VOID
change_channel(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	BYTE            temp[255];


	sprintf(temp, "Patch Mapping: '%s' to #%d", patch_names[(WORD) ptttree[PTT_PATCH].ob_spec.slider->curr - 1], (WORD) ptttree[PTT_CHANNEL].ob_spec.slider->curr);
	objc_xupdate(ptttree, PTT_TITLE, T_BX_TEXT, temp, 0);
	ob_draw(ptttree, PTT_TITLE, 0);
}


VOID
change_tune(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	LONG            o, h, f;

	o = tree[PTT_OCTAVE].ob_spec.slider->curr;
	h = tree[PTT_HALFSTEP].ob_spec.slider->curr;
	f = tree[PTT_FINE].ob_spec.slider->curr;
	patchtab[21 * (tree[PTT_PATCH].ob_spec.slider->curr - 1) + 3L] = ohf2tune(o, h, f);
}

VOID
change_volume(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	LONG            v;

	v = tree[PTT_VOLUME].ob_spec.slider->curr;
	patchtab[21 * (tree[PTT_PATCH].ob_spec.slider->curr - 1) + 20L] = (v << 8) + (v << 24);
}

/*
 * Compare fct for PTT list
 */
WORD
pttcmp(a, b)
	PTT_TAB        *a, *b;
{
	WORD            d;

	if ((d = (a->channel - b->channel)) == 0) {
		d = a->start - b->start;
	}
	return d;
}




/*
 * ==========================================================================
 * Main	Screen Button Bar
 */


/*
 * Loading & Saving	Patch Mab Tables ---------------------------------
 */

#define	PMT_EXT		 " *.pmt| *.*"
#define	PRF_EXT		 " *.prf| *.*"
#define	CURR_DIR  "."

/*
 * Load	Button
 */
EXTERN BYTE     pathbuf[];

VOID
load_handler(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{
	BYTE            path[256];
	BYTE            fname[16];
	WORD            x;

	objc_outline(tree, NIL, curr);
	v_dark_tree(tree);
	x = fsel_input("PRF", STR_LOADPRF, CURR_DIR, "", PRF_EXT, path, &fname[1]);

	if (x) {
		BYTE            bbuf[28];
		BYTE            dbuf[324];

		disable_sound();
		fname[0] = SLASH;
		strcat(path, fname);
		strrncpy(bbuf, path, 24);
		sprintf(dbuf, FMSTR_LOADPTT, path);
		form_alert(FRM_MSGSHOW, dbuf);
		/* read_pmp(path);	 */
		free_allSamples();
		init_patches();
		read_patch(PERF_FILE, path, 0);	/* read perf. file */
		form_alert(FRM_MSGCLOSE, NULL);
		enable_sound();
	}
	v_draw_title();
	objc_draw(maintree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, curr, NIL);
}


VOID
load_pmthandler(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{
	BYTE            path[256];
	BYTE            fname[16];
	WORD            x;

	objc_outline(tree, NIL, curr);
	v_dark_tree(tree);
	x = fsel_input("PMT", STR_LOADPMT, CURR_DIR, "", PMT_EXT, path, &fname[1]);

	if (x) {
		BYTE            bbuf[28];
		BYTE            dbuf[324];

		disable_sound();
		fname[0] = SLASH;
		strcat(path, fname);
		strrncpy(bbuf, path, 24);
		sprintf(dbuf, FMSTR_LOADPTT, path);
		form_alert(FRM_MSGSHOW, dbuf);
		read_pmp(path);
		form_alert(FRM_MSGCLOSE, NULL);
		enable_sound();
	}
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, curr, NIL);
}


VOID
save_handler(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{
	BYTE            path[256];
	BYTE            fname[16];
	WORD            x;

	objc_outline(tree, NIL, curr);
	v_dark_tree(tree);
	x = fsel_input("PRF", STR_SAVEPRF, CURR_DIR, "", PRF_EXT, path, &fname[1]);

	if (x) {
		BYTE            bbuf[28];
		BYTE            dbuf[324];

		disable_sound();
		fname[0] = SLASH;
		strcat(path, fname);
		strrncpy(bbuf, path, 24);
		sprintf(dbuf, FMSTR_SAVEPTT, &fname[1]);
		form_alert(FRM_MSGSHOW, dbuf);
		/* write_pmp(path); */
		write_patch(PERF_FILE, path, 0);	/* write	perf.
							 * file */
		form_alert(FRM_MSGCLOSE, NULL);
		enable_sound();
	}
	v_draw_title();
	objc_draw(maintree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, curr, NIL);
}


VOID
save_pmthandler(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{
	BYTE            path[256];
	BYTE            fname[16];
	WORD            x;

	objc_outline(tree, NIL, curr);
	v_dark_tree(tree);
	x = fsel_input("PMT", STR_SAVEPMT, CURR_DIR, "", PMT_EXT, path, &fname[1]);

	if (x) {
		BYTE            bbuf[28];
		BYTE            dbuf[324];

		fname[0] = SLASH;
		strcat(path, fname);
		strrncpy(bbuf, path, 24);
		sprintf(dbuf, FMSTR_SAVEPTT, &fname[1]);
		form_alert(FRM_MSGSHOW, dbuf);
		write_pmp(path);
		form_alert(FRM_MSGCLOSE, NULL);
	}
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, curr, NIL);
}



/*
 * Write Patch map
 */

WORD
write_pmp(fname)
	BYTE           *fname;
{
	BYTE            buf[256];
	REG WORD        i;
	REG BYTE       *s = filebuf;
	MFILE          *fp;

	if ((fp = mfopen(filebuf, "wa")) == NULL)
		return -1;

	mfputs("#ATPMAP - DO NOT REMOVE THIS LINE", fp);
	mfputs("#", fp);
	mfputs("# JAZ - JAGUAR AUDIO SYSTEM - PATCH MAP TABLE", fp);
	mfputs("#", fp);
	sprintf(buf, "# CH\tPATCH\tNOTE RANGE\tOFFSET\tPRI\tVOL\tTUNE", fp);
	mfputs(buf, fp);
	mfputs("#", fp);

	for (i = 0; i < ptt_count; i++) {
		sprintf(buf, "%d\t%d\t%s\t%s\t%s\t%s\t%s",
			ptt_table[i].channel - 1,
			ptt_table[i].patch - 1,
			ptt_table[i].s_note,
			ptt_table[i].s_offset,
			ptt_table[i].s_priority,
			ptt_table[i].s_volume,
			ptt_table[i].s_tuning);
		mfputs(buf, fp);
	}
	dos_write(fname, (LONG) fp->_cnt);
	mfclose(fp);
	return 0;
}


	WORD
read_pmp(fname)
	BYTE           *fname;
{
	BYTE            buf[256];
	REG WORD        i = 0;
	WORD            n;
	REG BYTE       *s;
	MFILE          *fp;
	WORD            ch, patch, note_b, note_e, offset, pri, vol;
	LONG            tune;
	LISTINFO       *list = jaztree[JAZ_PTTBOX].ob_spec.list;

	mk_patches_inactive();
	dos_read(fname);
	if ((fp = mfopen(filebuf, "ra")) == NULL)
		return -1;
	while (mfgets(buf, 256, fp) != NULL) {
		s = buf;
		for (; *s && (*s == '	') && (*s == '\t');)
			s++;
		if (!*s)
			continue;

		if (*s == '#' || *s == ';' || *s == '*')
			continue;
		n = sscanf(s, "%d %d %d -%d %d %d %d $%lx", &ch, &patch,
			   &note_b, &note_e, &offset, &pri, &vol, &tune);
		if (n == 8) {
			ptt_table[i].act = 0;
			ptt_table[i].channel = ch + 1;
			ptt_table[i].patch = patch + 1;
			ptt_table[i].start = note_b;
			ptt_table[i].end = note_e;
			ptt_table[i].offset = offset;
			ptt_table[i].priority = pri;
			ptt_table[i].volume = vol;
			ptt_table[i].tuning = tune;
			i++;
		}
	}
	list->maxitems = ptt_count = i;
	PttTable2Strings(-1);
	PttTable2PitchPatch();
	mk_patches_active();
	mfclose(fp);
}


VOID
pstab_handler(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{

	v_dark_tree(tree);
	objc_outline(tree, NIL, curr);

	objc_draw(pstabtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(pstabtree, PSTAB_PLIST);

	v_draw_title();
	objc_draw(maintree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, curr, NIL);
}

LONG
pstab_close(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{
	return -1L;
}

extern long     hog_on;

VOID
hog_handler(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3)
{
	hog_on ^= 1;
	release(0, 1);
}

VOID
pstab_prename(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3)
{
	v_dark_tree(tree);
	objc_outline(tree, NIL, obj);
	objc_xupdate(rentree, RENAME_NAME, T_EDIT_DATA, patch_names[pstabtree[PSTAB_PLIST].ob_spec.list->index], 0);
	objc_draw(rentree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);

	form_xdo(rentree, RENAME_BAR);

	strcpy(patch_names[pstabtree[PSTAB_PLIST].ob_spec.list->index], rentree[RENAME_NAME].ob_spec.textedit->data);
	update_patchnameslist();
	objc_draw(pstabtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, obj, NIL);
}

VOID
midi_handler(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3)
{
	v_dark_tree(tree);
	objc_outline(tree, NIL, obj);
	objc_draw(filtertree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(filtertree, MIDI_BAR);

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

VOID
midi_change_all(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3)
{
	WORD            i;

	midi_filter = 0L;
	for (i = MIDI_PRGCHANGE; i <= MIDI_MODUL; i++) {
		if (filtertree[i].ob_state & SELECTED)
			midi_filter |= 1 << (i - MIDI_PRGCHANGE);

	}
}

VOID
midi_set_all()
{
	WORD            i;

	for (i = MIDI_PRGCHANGE; i <= MIDI_MODUL; i++) {
		if ((midi_filter >> (i - MIDI_PRGCHANGE)) & 1) {
			filtertree[i].ob_state |= SELECTED;
		}
	}
}


VOID
global_handler(OBJECT * tree, WORD obj, WORD d1, WORD d2, ULONG d3)
{
	objc_outline(tree, NIL, obj);
	v_dark_tree(tree);

	globaltree[GLOBAL_EFFECT].ob_spec.popup->index = check_delay();

	objc_draw(globaltree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(globaltree, GLOBAL_EFFECT);

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

VOID
change_surround(OBJECT * tree, WORD obj, SLINTINFO * info)
{
	effect_channel = info->intval;
}


LONG
pmt_omni(tree, curr, found, n, k)
	OBJECT         *tree;
	WORD            curr;
	WORD            found;
	WORD            n;
	ULONG           k;
{
	LISTINFO       *list = jaztree[JAZ_PTTBOX].ob_spec.list;

	pmt_omni_mode = !pmt_omni_mode;

	if (pmt_omni_mode) {
		curr_pnr = ptt_table[list->index].patch - 1;
		curr_patch = &patchtab[curr_pnr];
	}
	return 0L;

}

VOID
pttlist_scrolled(tree, obj, info)
	OBJECT         *tree;
	WORD            obj;
	LISTINFO       *info;
{
	LISTINFO       *list = jaztree[JAZ_PTTBOX].ob_spec.list;

	if (pmt_omni_mode) {
		curr_pnr = ptt_table[list->index].patch - 1;
		curr_patch = &patchtab[curr_pnr];
	}
}




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

	WORD x;

	x = info->index;

	switch (x) {
	case 0:
		gl_pitchbend = 12;
		break;
	case 1:
		gl_pitchbend = 2;		
		break;
	
	}
}

