/********************************************************************
 *																	*
 *	Extended resource objects module								*
 *																	*
 *	Copyright (c) Clever Bits and Bitgate Software 1993 - 1994		*
 *	All Rights Reserved.											*
 *																	*
 *	This modules deals with all extended objects plus all "fixing"	*
 *	of resource objects, eg. scaling of icons and bitmaps to fit	*
 *	resolutions.													*
 *																	*
 ********************************************************************
 *																	*
 *	Update log:														*
 *																	*
 *	[14.7.93 - 31.10.93] Ken Hollis									*
 *		pb_textout			- added several different drawing styles*
 *	[31.10.93 - 18.3.94] Karl A. 0ygard and Ken Hollis				*
 *		(global)			- worked further on EObTs				*
 *							- added more images for your pleasure	*
 *							- changed some images, added animation	*
 *							- changed box, circle, and cycle buttons*
 *							- added the DROPDOWN icon				*
 *							- added clipping to ALL graphics		*
 *		fix_object			- fixed a size problem with CUSTOM		*
 *		pb_doobject			- fixed colors for four-color monitors	*
 *							- fixed L_GENEVA type to look correct	*
 *							- added inverted hotkey option			*
 *							- added custom disabled state			*
 *		draw_custbutton		- optimized and fixed some incoherence	*
 *							- added CUSTBTN and CYCLEBTN looks		*
 *							- added image copy within routine		*
 *							- added switching for optimizations		*
 *							- added DROPDOWN type					*
 *							- added color icon stuff				*
 *		draw_boxframe		- added for grouping related items		*
 *							- added boxed title (with colors)		*
 *							- added WHITEBACK check for 3D effect	*
 *							- updated WHITEBACK drawing method		*
 *		draw_menuline		- added for menu separators (better)	*
 *																	*
 ********************************************************************/

#include <aes.h>
#include <vdi.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>

#include "winlib.h"

#ifdef __TURBOC__
#pragma warn -pia
#endif

#ifndef __EXTENDEDOBJ__
#define __EXTENDEDOBJ__
#endif

static int *cycle_on, *cycle_off, *box_on, *box_off, *radio_on,
		*radio_off, *up_on, *up_off, *down_on, *down_off, *left_on,
		*left_off, *right_on, *right_off, *dropdown_on, *dropdown_off;
int draw3dtype;

static int radio_hi_on[] =
{
	0x0000, 0x03E0, 0x0FF8, 0x1C0C, 0x3942, 0x32A2, 0x6551, 0x6AA9, 
	0x6551, 0x6AA9, 0x6551, 0x22A2, 0x3142, 0x1004, 0x0C18, 0x03E0, 
	0x07C0, 0x1830, 0x2008, 0x47C4, 0x4FE4, 0x9FF2, 0x9FF2, 0x9FF2, 
	0x9FF2, 0x9FF2, 0x4FE4, 0x47C4, 0x2008, 0x1830, 0x07C0, 0x0000, 
	0x0000, 0x03C0, 0x0C30, 0x1008, 0x23C4, 0x27E4, 0x4FF2, 0x4FF2, 
	0x4FF2, 0x4FF2, 0x27E4, 0x23C4, 0x1008, 0x0C30, 0x03C0, 0x0000, 
	0x0000, 0x03C0, 0x0C30, 0x1188, 0x27E4, 0x2FF4, 0x4FF2, 0x5FFA, 
	0x5FFA, 0x4FF2, 0x2FF4, 0x27E4, 0x1188, 0x0C30, 0x03C0, 0x0000, 
	0x0000, 0x0000, 0x03C0, 0x0C30, 0x1008, 0x13C8, 0x27E4, 0x27E4, 
	0x27E4, 0x27E4, 0x13C8, 0x1008, 0x0C30, 0x03C0, 0x0000, 0x0000, 
	0x0000, 0x43C2, 0x2C34, 0x1008, 0x2814, 0x2424, 0x4242, 0x4182, 
	0x4182, 0x4242, 0x2424, 0x2814, 0x1008, 0x2C34, 0x43C2, 0x0000, 
	0x0000, 0x03C0, 0x0C30, 0x1008, 0x23C4, 0x2624, 0x4F92, 0x4FD2, 
	0x4FF2, 0x4FF2, 0x27E4, 0x23C4, 0x1008, 0x0C30, 0x03C0, 0x0000, 
	0x0000, 0x03C0, 0x0C30, 0x1008, 0x23C4, 0x27E4, 0x4FF2, 0x4FF2, 
	0x4FF2, 0x4FF2, 0x27E4, 0x23C4, 0x1008, 0x0C30, 0x03C0, 0x0000
};
	
static int radio_hi_off[] =
{
	0x0000, 0x03E0, 0x0C18, 0x1004, 0x2006, 0x2002, 0x4003, 0x4003, 
	0x4003, 0x4003, 0x4003, 0x2006, 0x200E, 0x181C, 0x0FF8, 0x03E0,
	0x07C0, 0x1830, 0x2008, 0x4004, 0x4004, 0x8002, 0x8002, 0x8002, 
	0x8002, 0x8002, 0x4004, 0x4004, 0x2008, 0x1830, 0x07C0, 0x0000, 
	0x0000, 0x03C0, 0x0C30, 0x1008, 0x2004, 0x2004, 0x4002, 0x4002, 
	0x4002, 0x4002, 0x2004, 0x2004, 0x1008, 0x0C30, 0x03C0, 0x0000, 
	0x0000, 0x0000, 0x03C0, 0x0C30, 0x1008, 0x1008, 0x2004, 0x2004, 
	0x2004, 0x2004, 0x1008, 0x1008, 0x0C30, 0x03C0, 0x0000, 0x0000, 
	0x0000, 0x03C0, 0x0C30, 0x1008, 0x23C4, 0x2424, 0x4812, 0x4812, 
	0x4812, 0x4812, 0x2424, 0x23C4, 0x1008, 0x0C30, 0x03C0, 0x0000
};

static int radio_lo_on[] =
{
	0x07C0, 0x3838, 0x638C, 0xCFE6, 0xCFE6, 0x638C, 0x3838, 0x07C0
};

static int radio_lo_off[] =
{
	0x07C0, 0x3838, 0x600C, 0xC006, 0xC006, 0x600C, 0x3838, 0x07C0
};

static int check_hi_on[] =
{
	0x0000, 0x7FFF, 0x4001, 0x580D, 0x5C1D, 0x4E39, 0x4771, 0x43E1, 
	0x41C1, 0x43E1, 0x4771, 0x4E39, 0x5C1D, 0x580D, 0x4001, 0x7FFF, 
	0x0000, 0x7FFE, 0x6006, 0x500A, 0x4812, 0x4422, 0x4242, 0x4182, 
	0x4182, 0x4242, 0x4422, 0x4812, 0x500A, 0x6006, 0x7FFE, 0x0000, 
	0x0000, 0x7FFE, 0x4002, 0x500A, 0x4812, 0x4422, 0x4242, 0x4182, 
	0x4182, 0x4242, 0x4422, 0x4812, 0x500A, 0x4002, 0x7FFE, 0x0000, 
	0x0000, 0x4002, 0x3FFC, 0x300C, 0x2814, 0x2424, 0x2244, 0x2184, 
	0x2184, 0x2244, 0x2424, 0x2814, 0x300C, 0x3FFC, 0x4002, 0x0000
};

static int check_hi_off[] =
{
	0x0000, 0x7FFF, 0x4001, 0x4001, 0x4001, 0x4001, 0x4001, 0x4001, 
	0x4001, 0x4001, 0x4001, 0x4001, 0x4001, 0x4001, 0x4001, 0x7FFF, 
	0x0000, 0x7FFE, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 
	0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x7FFE, 0x0000, 
	0x0000, 0x0000, 0x3FFC, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 
	0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x3FFC, 0x0000, 0x0000
};

static int check_lo_on[] = 
{
	0xFFFE, 0xB01A, 0x8C62, 0x8382, 0x8C62, 0xB01A, 0xFFFE, 0x0000
};

static int check_lo_off[] = 
{
	0xFFFE, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xFFFE, 0x0000
};

static int cycle_sel[] =
{
	0x07E0, 0x5C1C, 0x7806, 0x7C00, 0x003E, 0x601E, 0x383A, 0x07E0
};

static int down_arrow_sel[] =
{
	0xFFFE, 0x7FFC, 0x3FF8, 0x1FF0, 0x0FE0, 0x07C0, 0x0380, 0x0100
};

static int down_arrow_unsel[] =
{
	0xFFFE, 0x4004, 0x2008, 0x1010, 0x0820, 0x0440, 0x0280, 0x0100
};

static int left_arrow_sel[] =
{
	0x0000, 0x000F, 0x00FF, 0x0FFF, 0xFFFF, 0x0FFF, 0x00FF, 0x000F
};

static int left_arrow_unsel[] =
{
	0x0000, 0x000F, 0x00F1, 0x0F01, 0xF001, 0x0F01, 0x00F1, 0x000F
};

static int right_arrow_sel[] =
{
	0x0000, 0xF800, 0xFF80, 0xFFF8, 0xFFFF, 0xFFF8, 0xFF80, 0xF800
};

static int right_arrow_unsel[] =
{
	0x0000, 0xF800, 0x8780, 0x8078, 0x8007, 0x8078, 0x8780, 0xF800
};

static int up_arrow_sel[] =
{
	0x0100, 0x0380, 0x07C0, 0x0FE0, 0x1FF0, 0x3FF8, 0x7FFC, 0xFFFE
};

static int up_arrow_unsel[] =
{
	0x0100, 0x0280, 0x0440, 0x0820, 0x1010, 0x2008, 0x4004, 0xFFFE
};

static int dropdown_unsel[] =
{
	0x0000, 0x7FFE, 0x0000, 0x7FFE, 0x1FF8, 0x07E0, 0x0180, 0x0000
};

static IMAGE radio_im[] =
{
	{radio_hi_on + 32, radio_hi_off + 32, radio_lo_on, radio_lo_off}, 
	{radio_hi_on, radio_hi_off, NULL, NULL}, 
	{radio_hi_on + 16, radio_hi_off + 16, NULL, NULL}, 
	{radio_hi_on + 48, radio_hi_off + 32, NULL, NULL}, 
	{radio_hi_on + 64, radio_hi_off + 48, NULL, NULL}, 
	{radio_hi_on + 80, radio_hi_off + 32, NULL, NULL}, 
	{radio_hi_on + 96, radio_hi_off + 64, NULL, NULL}, 
	{radio_hi_on + 112, radio_hi_off + 64, NULL, NULL}
};

static IMAGE check_im[] =
{
	{check_hi_on + 16, check_hi_off + 16, check_lo_on, check_lo_off}, 
	{check_hi_on, check_hi_off, NULL, NULL}, 
	{check_hi_on + 32, check_hi_off + 32, NULL, NULL}, 
	{check_hi_on + 32, check_hi_off + 16, NULL, NULL}, 
	{check_hi_on + 48, check_hi_off + 32, NULL, NULL}
};

static IMAGE cycle_im[] =
{
	{NULL, NULL, cycle_sel, cycle_sel}
};

static IMAGE down_im[] =
{
	{NULL, NULL, down_arrow_sel, down_arrow_unsel}
};

static IMAGE up_im[] =
{
	{NULL, NULL, up_arrow_sel, up_arrow_unsel}
};

static IMAGE left_im[] =
{
	{NULL, NULL, left_arrow_sel, left_arrow_unsel}
};

static IMAGE right_im[] =
{
	{NULL, NULL, right_arrow_sel, right_arrow_unsel}
};

static IMAGE dropdown_im[] =
{
	{NULL, NULL, dropdown_unsel, dropdown_unsel}
};

IMAGES radios = {8, radio_im};
IMAGES checks = {5, check_im};
IMAGES cycles = {1, cycle_im};
IMAGES uparrow = {1, up_im};
IMAGES dnarrow = {1, down_im};
IMAGES lfarrow = {1, left_im};
IMAGES rtarrow = {1, right_im};
IMAGES dropdown = {1, dropdown_im};

GLOBAL void Change3DType(int type)
{
	draw3dtype = type;
}

GLOBAL void set_images(IMAGES *images, int **on, int **off)
{
	register IMAGE *im = images->image;
	register int i;
	int dummy;

	for (i = 0; i < images->count; i++) {
		vdi_trans(16, 16, im->hi_on);
		vdi_trans(16, 16, im->hi_off);

		if (big_img != TRUE) {
			if (!im->lo_on || big_img == FAIL)
				scale_img(im->hi_on, 16, 16, DARK_SCALING, &dummy, &dummy);
			else {
				im->hi_on = im->lo_on;
				vdi_trans(16, 8, im->hi_on);
			}

			if (!im->lo_off || big_img < 0)
				scale_img(im->hi_off, 16, 16, DARK_SCALING, &dummy, &dummy);
			else {
				im->hi_off = im->lo_off;
				vdi_trans(16, 8, im->hi_off);
			}
		}

		im++;
	}

	if (images->count > 0) {
		*on = images->image->hi_on;

		if (off)
			*off = images->image->hi_off;
	}
}

/*
 *	Blit image onto screen
 */
GLOBAL void vrt_copy(int *image, PARMBLK *pb, int color, int selected)
{
	register MFDB src;
	register int pxy[8], col[2], off = (big_img < 0) ? 1 : 0;
	register int attr[10];

	pxy[0] = pxy[1] = 0;
	pxy[2] = image_w - 1;
	pxy[3] = image_h - 1;
	pxy[4] = pb->pb_x + (gr_cw - (image_w >> 1)) + off;
	pxy[5] = pb->pb_y + ((gr_ch - image_h) >> 1) + off;
	pxy[6] = pxy[4] + pxy[2];
	pxy[7] = pxy[5] + pxy[3];

	if (selected) {
		col[1] = color;
		col[0] = 0;
	} else {
		col[0] = color;
		col[1] = 0;
	}

	init_mfdb(&src, image, 16, image_h, 0, 1);

	vqt_attributes(VDIhandle, attr);
	vrt_cpyfm(VDIhandle, MD_REPLACE, pxy, &src, &screen, col);
	vswr_mode(VDIhandle, attr[5]);
}

/*
 *	Output object
 *
 *	*pb = pointer to PARMBLK structure containing data
 *
 *	Returns: nothing
 */
LOCAL void pb_doobject(PARMBLK *pb, int xoff, int yoff)
{
	int dummy, effects = 0;
	int interiorpxy[4], pa[6];
	int extent[8], x, y;
	EXTINFO *ex = (EXTINFO *) pb->pb_parm;
	int oldtype = ex->oldtype & 0xff;
	char *ptr, *string, *unformatted = ex->te_ptext;
	int hotkey = -1, i = 0;
	int flags = pb->pb_tree[pb->pb_obj].ob_flags;
	int this_ch, this_bw;

	XVDI_SaveHandles();

	pa[0] = pb->pb_xc;
	pa[1] = pb->pb_yc;
	pa[2] = pb->pb_xc + pb->pb_wc - 1;
	pa[3] = pb->pb_yc + pb->pb_hc - 1;
	vs_clip(VDIhandle, 1, pa);

	if (ptr = string = strdup(unformatted)) {
		while (*unformatted) {
			if (*unformatted == '[')
				if (*(++unformatted))
					hotkey = i;
				else
					break;

			*(ptr++) = *(unformatted++);
			i++;
		}
		*ptr = 0;

		if (xoff) pb->pb_x += xoff;
		if (yoff) pb->pb_y += yoff;

		vst_height(VDIhandle, ex->te_font == 3 ? large_font : small_font, &dummy, &this_ch, &this_bw, &dummy);
		vst_color(VDIhandle, ex->te_color.text_color);
		vswr_mode(VDIhandle, MD_TRANS);

		if (pb->pb_currstate & 0x100) effects |= 1;
		if (pb->pb_currstate & 0x200) effects |= 8;
		if (pb->pb_currstate & 0x400) effects |= 4;
		if (pb->pb_currstate & 0x800) effects |= 2;
		if (pb->pb_currstate & 0x1000) effects |= 16;

		vst_effects(VDIhandle, effects);
		vqt_extent(VDIhandle, string, extent);

		{
 			int add = draw3dtype == L_CUSTOM ? 1 : 0;

			interiorpxy[2] = (interiorpxy[0] = pb->pb_x + add) + pb->pb_w - (add * 2);
			interiorpxy[3] = (interiorpxy[1] = pb->pb_y + add) + pb->pb_h - (add * 2);
		}

		if (ex->te_thickness < 0) {
			interiorpxy[0] -= ex->te_thickness;
			interiorpxy[1] -= ex->te_thickness;
			interiorpxy[2] += ex->te_thickness;
			interiorpxy[3] += ex->te_thickness;
		}

		if (ex->te_thickness > 0) {
			interiorpxy[0] += ex->te_thickness;
			interiorpxy[1] += ex->te_thickness;
			interiorpxy[2] -= ex->te_thickness;
			interiorpxy[3] -= ex->te_thickness;
		}

		interiorpxy[2]--;
		interiorpxy[3]--;

		switch (oldtype) {
			default:
				if ((draw3dtype == L_CUSTOM || draw3dtype == L_MOTIF) && num_colors>4) {
					extent[0]++;
					extent[1]++;
				}

				if (!((interiorpxy[2] - interiorpxy[0]) >= (extent[2] - extent[0]) &&
					  (interiorpxy[3] - interiorpxy[1]) >= (extent[7] - extent[1])))
				break;

			case G_BOX:
			case G_BOXTEXT:
			case G_BOXCHAR:
			case G_IBOX: {
					int pxyarray[16];

					if (ex->te_thickness) {
						int count, maxima;

						vsl_color(VDIhandle, ex->te_color.bord_color);

						if (ex->te_thickness < 0)
							maxima = 1 - min(ex->te_thickness, 0);
						else
							maxima = max(ex->te_thickness, 0) + 1;

						switch (draw3dtype) {
							case L_MULTITOS:
							case L_GENEVA:
							case L_STANDARD:
								if ((flags & 0x600) != 0x400) {
									for (count = 0; count < maxima; count++)
										box(pb->pb_x + count, pb->pb_y + count, pb->pb_w - ((2 * count) + 1), pb->pb_h - ((2 * count) + 1), 1);
									break;
								}

							case L_CUSTOM:
							case L_MOTIF: {
									int i, col1, col2;

									if (pb->pb_currstate & SELECTED && flags & 0x0400)
										col1 = 0, col2 = 9;
									else
										col1 = 9, col2 = 0;

									if (draw3dtype == L_CUSTOM || draw3dtype == L_MOTIF && draw3dtype != L_STANDARD) {
										vsl_color(VDIhandle, col1);
										for (i = 0; i < maxima; i++) {
											pxyarray[0] = pb->pb_x + i;
											pxyarray[1] = pxyarray[3] = pb->pb_y + pb->pb_h - (i + 1);
											pxyarray[2] = pxyarray[4] = pb->pb_x + pb->pb_w - (i + 1);
											pxyarray[5] = pb->pb_y + i;
											v_pline(VDIhandle, 3, pxyarray);
										}

										vsl_color(VDIhandle, col2);
										for (i = 0; i < maxima; i++) {
											pxyarray[0] = pxyarray[2] = pb->pb_x + i;
											pxyarray[1] = pb->pb_y + pb->pb_h - (i + 1);
											pxyarray[3] = pxyarray[5] = pb->pb_y + i;
											pxyarray[4] = pb->pb_x + pb->pb_w - (i + 1);
											v_pline(VDIhandle, 3, pxyarray);
										}

										vsm_color(VDIhandle, (num_colors>4) ? 8 : 0);
										for (i = 0; i < maxima; i++) {
											pxyarray[0] = pb->pb_x + i;
											pxyarray[1] = pb->pb_y + pb->pb_h - (i + 1);
											pxyarray[2] = pb->pb_x + pb->pb_w - (i + 1);
											pxyarray[3] = pb->pb_y + i;
											v_pmarker(VDIhandle, 2, pxyarray);
										}

										if (draw3dtype != L_MOTIF)
											box(pb->pb_x, pb->pb_y, pb->pb_w - 1, pb->pb_h - 1, 1);
									}
								}
								break;
						}
					}

					if (oldtype != G_IBOX) {
						if (num_colors > 4 && flags & 0x600)
							vsf_color(VDIhandle, 8);
						else
							vsf_color(VDIhandle, 0);

						if (draw3dtype==L_STANDARD)
							vsf_color(VDIhandle, 0);

						vsf_interior(VDIhandle, FIS_SOLID);
						vr_recfl(VDIhandle, interiorpxy);
					}

					if (ex->te_color.fill_ptn) {
						vsf_style(VDIhandle, ex->te_color.fill_ptn == 7 ? 8 : ex->te_color.fill_ptn);
						vsf_interior(VDIhandle, FIS_PATTERN);
						vsf_color(VDIhandle, ex->te_color.in_color);
						vr_recfl(VDIhandle, interiorpxy);
					}

					if (flags & 0x200 && (draw3dtype == L_MULTITOS || draw3dtype == L_GENEVA)) {
						int col1, col2;

						if (pb->pb_currstate & SELECTED && flags & 0x400)
							col1 = 1, col2 = ((draw3dtype==L_GENEVA) && num_colors>4) ? 8 : 0;
						else
							col1 = 0, col2 = 9;

						vsl_color(VDIhandle, col1);
						pxyarray[0] = pxyarray[2] = interiorpxy[0];
						pxyarray[1] = (draw3dtype==L_GENEVA) ? interiorpxy[3] : interiorpxy[3] - 1;
						pxyarray[3] = pxyarray[5] = interiorpxy[1];
						pxyarray[4] = (draw3dtype==L_GENEVA) ? interiorpxy[2] : interiorpxy[2] - 1;
						v_pline(VDIhandle, 3, pxyarray);

						vsl_color(VDIhandle, col2);
						pxyarray[0] = pxyarray[0] + 1;
						pxyarray[1] = pxyarray[3] = interiorpxy[3];
						pxyarray[2] = pxyarray[4] = interiorpxy[2];
						pxyarray[5] = interiorpxy[1] + 1;
						v_pline(VDIhandle, 3, pxyarray);

						if (draw3dtype!=L_GENEVA) {
							vsm_color(VDIhandle, (num_colors>4) ? 8 : 0);
							pxyarray[0] = interiorpxy[0];
							pxyarray[1] = interiorpxy[3];
							pxyarray[2] = interiorpxy[2];
							pxyarray[3] = interiorpxy[1];
							v_pmarker(VDIhandle, 2, pxyarray);
						}
					}
				}

			case G_FTEXT:
			case G_STRING:
			case G_TEXT:
				if ((oldtype != G_BOX) &&
					(((ex->oldtype >> 8) != CUSTBTN) &&
					((ex->oldtype >> 8) != CYCLEBTN)) &&
					((ex->oldtype >> 8) != DROPDOWN)) {
					y = pb->pb_y + ((pb->pb_h - (extent[7] - extent[1])) / 2) + this_ch;
					x = pb->pb_x;

					if (draw3dtype!=L_STANDARD) {
						if (pb->pb_currstate & SELECTED && flags & 0x400) {
							y++;
							x++;
						}
					}

					switch (ex->te_just) {
						case 2:
							x += (pb->pb_w - (extent[2] - extent[0])) / 2;
							break;
						case 1:
							x += pb->pb_w - (extent[2] - extent[0]);
							break;
					}

					if (pb->pb_currstate & 0x2000 && draw3dtype!=L_STANDARD) {
						vst_effects(VDIhandle, effects | 2);
						v_gtext(VDIhandle, x + 2, y + 2, string);
						vst_effects(VDIhandle, effects);
					}

					if ((draw3dtype == L_CUSTOM || draw3dtype == L_MOTIF) && (num_colors > 4) && draw3dtype!=L_STANDARD) {
						vst_color(VDIhandle, 0);
						v_gtext(VDIhandle, x - 1, y - 1, string);
					}

					vst_color(VDIhandle, ex->te_color.text_color);
					v_gtext(VDIhandle, x, y, string);

					if (hotkey >= 0) {
						int pxyarray[4];

						if ((draw3dtype == L_CUSTOM || draw3dtype == L_MOTIF) && (num_colors > 4)) {
							vsl_color(VDIhandle, 0);

							if (hotkeylevel == HOTKEY_UNDERLINE) {
								pxyarray[2] = ((pxyarray[0] = (x + this_bw * hotkey) - 1) + this_bw);
								pxyarray[1] = (pxyarray[3] = (y + this_ch / 6) - 1);
								v_pline(VDIhandle, 2, pxyarray);

								vst_color(VDIhandle, 0);
								v_gtext(VDIhandle, x - 1, y - 1, string);
							}
						}

						vsl_color(VDIhandle, ex->te_color.text_color);

						if (hotkeylevel == HOTKEY_UNDERLINE) {
							pxyarray[2] = (pxyarray[0] = x + this_bw * hotkey) + this_bw;
							pxyarray[1] = pxyarray[3] = y + this_ch / 6;
							v_pline(VDIhandle, 2, pxyarray);

							vst_color(VDIhandle, ex->te_color.text_color);
							v_gtext(VDIhandle, x, y, string);
						}
					}
				}
				break;
		}

		if (pb->pb_currstate & SELECTED && (!(flags & 0x400) || (draw3dtype==L_STANDARD))) {
			vsf_interior(VDIhandle, FIS_SOLID);
			vsf_color(VDIhandle, 1);
			vswr_mode(VDIhandle, MD_XOR);
			vr_recfl(VDIhandle, interiorpxy);
		}

		if (hotkey >= 0)
			if (hotkeylevel == HOTKEY_INVERSE) {
				int pxyarray[4];

				pxyarray[0] = (x + gr_cw * hotkey);
				pxyarray[1] = (y + this_ch / 6) - (this_ch + 2);
				pxyarray[2] = (x + gr_cw * hotkey) + (gr_cw - 1);
				pxyarray[3] = (y + this_ch / 6);

				if (oldtype!=G_BOX || oldtype!=G_BOXTEXT || oldtype!=G_BUTTON) {
					vst_color(VDIhandle, 0);
					vswr_mode(VDIhandle, MD_TRANS);
					v_gtext(VDIhandle, x - 1, y - 1, string);

					vsf_interior(VDIhandle, FIS_SOLID);
					vsf_color(VDIhandle, 0);
					vswr_mode(VDIhandle, MD_REPLACE);
					vr_recfl(VDIhandle, pxyarray);

					vst_color(VDIhandle, ex->te_color.text_color);
					vswr_mode(VDIhandle, MD_TRANS);
					v_gtext(VDIhandle, x, y, string);

					vsf_interior(VDIhandle, FIS_SOLID);
					vsf_color(VDIhandle, 1);
					vswr_mode(VDIhandle, MD_XOR);
					vr_recfl(VDIhandle, pxyarray);
				} else {
					vsf_interior(VDIhandle, FIS_SOLID);
					vsf_color(VDIhandle, 1);
					vswr_mode(VDIhandle, MD_REPLACE);
					vr_recfl(VDIhandle, pxyarray);

					vst_color(VDIhandle, 0);
					vswr_mode(VDIhandle, MD_TRANS);
					v_gtext(VDIhandle, x, y, string);

					vswr_mode(VDIhandle, MD_XOR);
					vst_color(VDIhandle, ex->te_color.text_color);
					v_gtext(VDIhandle, x, y, string);
				}
			}

		if (pb->pb_currstate & DISABLED) {
			vsf_interior(VDIhandle, FIS_PATTERN);

			interiorpxy[0] = pb->pb_x;
			interiorpxy[1] = pb->pb_y;
			interiorpxy[2] = pb->pb_x + pb->pb_w - 1;
			interiorpxy[3] = pb->pb_y + pb->pb_h - 1;

			if (num_planes >= 4)
				vsf_color(VDIhandle, 8);
			else
				vsf_color(VDIhandle, 0);

			vsf_style(VDIhandle, 4);
			vswr_mode(VDIhandle, MD_TRANS);
			vr_recfl(VDIhandle, interiorpxy);
		}

		if (xoff) pb->pb_x -= xoff;
		if (yoff) pb->pb_y -= yoff;

		free(string);
	}

	XVDI_RestoreHandles();
}

/*
 *	Userdefined text proc
 */
LOCAL int cdecl draw_specialtext(PARMBLK *pb)
{
	int pxyarray[4];

	pb_doobject(pb, 0, 0);

	return pb->pb_currstate & ~(SELECTED | OUTLINED);
}

/*
 *	Userdefined underline proc
 */
LOCAL int cdecl draw_underline(PARMBLK *pb)
{
	int pxyarray[4];

	pb_doobject(pb, 0, 0);

	XVDI_SaveHandles();

	pxyarray[0] = pb->pb_xc;
	pxyarray[1] = pb->pb_yc;
	pxyarray[2] = pb->pb_xc + pb->pb_wc - 1;
	pxyarray[3] = pb->pb_yc + pb->pb_hc - 1;
	vs_clip(VDIhandle, 1, pxyarray);

	if (pb->pb_tree[pb->pb_obj].ob_state & DISABLED) {
		vsl_type(VDIhandle, 7);
		vsl_udsty(VDIhandle, 0x5555);
	}

	vsl_color(VDIhandle, ((EXTINFO *) pb->pb_parm)->te_color.bord_color);

	pxyarray[0] = pb->pb_x;
	pxyarray[2] = pb->pb_x + pb->pb_w;
	pxyarray[1] = pxyarray[3] = pb->pb_y + pb->pb_h;
	v_pline(VDIhandle, 2, pxyarray);

	XVDI_RestoreHandles();

	return FALSE;
}

/*
 *	Userdefined boxframe procedure
 */
LOCAL int cdecl draw_boxframe(PARMBLK *pb)
{
	int pxyarray[10], dummy;
	EXTINFO *ex = (EXTINFO *) pb->pb_parm;
	char *unformatted = ex->te_ptext;
	int state = pb->pb_tree[pb->pb_obj].ob_state;
	int disabled = pb->pb_tree[pb->pb_obj].ob_state & DISABLED;
	int this_ch, this_bw;

	XVDI_SaveHandles();

	pxyarray[0] = pb->pb_xc;
	pxyarray[1] = pb->pb_yc;
	pxyarray[2] = pb->pb_xc + pb->pb_wc - 1;
	pxyarray[3] = pb->pb_yc + pb->pb_hc - 1;
	vs_clip(VDIhandle, 1, pxyarray);

	vswr_mode(VDIhandle, MD_REPLACE);
	vsl_color(VDIhandle, ((EXTINFO *) pb->pb_parm)->te_color.bord_color);

	if ((num_colors<=4) || !(state & DRAW3D) || (draw3dtype == L_STANDARD))
		box(pb->pb_x, pb->pb_y, pb->pb_w - 1, pb->pb_h - 1, ((EXTINFO *) pb->pb_parm)->te_color.bord_color);

	if ((state & DRAW3D) && (num_colors > 4) && (draw3dtype!=L_STANDARD)) {
		vsl_color(VDIhandle, 9);
		pxyarray[0] = pb->pb_x + pb->pb_w - 1;
		pxyarray[1] = pxyarray[3] = pb->pb_y;
		pxyarray[2] = pxyarray[4] = pb->pb_x;
		pxyarray[5] = pb->pb_y + pb->pb_h - 1;
		v_pline(VDIhandle, 3, pxyarray);

		vsl_color(VDIhandle, 0);
		pxyarray[0] = pxyarray[2] = pb->pb_x + pb->pb_w - 1;
		pxyarray[1] = pb->pb_y + 1;
		pxyarray[3] = pxyarray[5] = pb->pb_y + pb->pb_h - 1;
		pxyarray[4] = pb->pb_x + 1;
		v_pline(VDIhandle, 3, pxyarray);

		vsf_interior(VDIhandle, FIS_SOLID);

		if (state & WHITEBACK)
			vsf_color(VDIhandle, WHITE);
		else
			vsf_color(VDIhandle, 8);

		pxyarray[0] = pb->pb_x + 1;
		pxyarray[1] = pb->pb_y + 1;
		pxyarray[2] = pb->pb_x + pb->pb_w - 3;
		pxyarray[3] = pb->pb_y + pb->pb_h - 3;
		vr_recfl(VDIhandle, pxyarray);

		box(pb->pb_x + 1, pb->pb_y + 1, pb->pb_w - 3, pb->pb_h - 3, (state & WHITEBACK) ? 8 : WHITE);

		if (!(state & WHITEBACK)) {
			vsl_color(VDIhandle, 9);

			pxyarray[0] = pxyarray[2] = pb->pb_x + pb->pb_w - 2;
			pxyarray[1] = pb->pb_y + 2;
			pxyarray[3] = pxyarray[5] = pb->pb_y + pb->pb_h - 2;
			pxyarray[4] = pb->pb_x + 2;

			v_pline(VDIhandle, 3, pxyarray);
		}
	}

	vst_height(VDIhandle, ex->te_font == 3 ? large_font : small_font, &dummy, &this_ch, &this_bw, &dummy);
	v_gtext(VDIhandle, pb->pb_x + gr_cw, pb->pb_y + (this_ch / 2), unformatted);

	if (pb->pb_tree[pb->pb_obj].ob_flags & BOXFRAMETITLE) {
		vsl_color(VDIhandle, 9);
		pxyarray[0] = pxyarray[2] = pb->pb_x + gr_cw;
		pxyarray[1] = pxyarray[7] = pb->pb_y;
		pxyarray[3] = pxyarray[5] = pb->pb_y - (gr_ch / 2);
		pxyarray[4] = pxyarray[6] = pb->pb_x + (int)((strlen(unformatted) + 1) * gr_cw);
		v_pline(VDIhandle, 4, pxyarray);

		vsl_color(VDIhandle, 8);
		pxyarray[0] = pxyarray[2] = pb->pb_x + gr_cw;
		pxyarray[1] = pxyarray[7] = pb->pb_y + 1;
		pxyarray[3] = pxyarray[5] = pb->pb_y + (gr_ch / 2) + 1;
		pxyarray[4] = pxyarray[6] = pb->pb_x + (int)((strlen(unformatted) + 1) * gr_cw);
		v_pline(VDIhandle, 4, pxyarray);
	}

	XVDI_RestoreHandles();

	return pb->pb_currstate | disabled;
}

/*
 *	Userdefined buttons
 */
LOCAL int cdecl draw_custbutton(PARMBLK *pb)
{
	static int IMask0Mon[] = {0x07C0,0x1FF0,0x3FF8,0x7FFC,0x7FFC,0xFFFE,0xFFFE,0xFFFE,
							   0xFFFE,0xFFFE,0x7FFC,0x7FFC,0x3FF8,0x1FF0,0x07C0,0x0000};
	static int IData0Mon[] = {0x07C0,0x1830,0x2008,0x4004,0x4004,0x8002,0x8002,0x8002,
							   0x8002,0x8002,0x4004,0x4004,0x2008,0x1830,0x07C0,0x0000};
	static int SMask0Mon[] = {0x07C0,0x1FF0,0x3FF8,0x7FFC,0x7FFC,0xFFFE,0xFFFE,0xFFFE,
							   0xFFFE,0xFFFE,0x7FFC,0x7FFC,0x3FF8,0x1FF0,0x07C0,0x0000};
	static int SData0Mon[] = {0x07C0,0x1830,0x2008,0x4384,0x47C4,0x8FE2,0x9FF2,0x9FF2,
							   0x9FF2,0x8FE2,0x47C4,0x4384,0x2008,0x1830,0x07C0,0x0000};
	static int IMask0Col[] = {0x07C0,0x1FF0,0x3FF8,0x7FFC,0x7FFC,0xFFFE,0xFFFE,0xFFFE,
							   0xFFFE,0xFFFE,0x7FFC,0x7FFC,0x3FF8,0x1FF0,0x07C0,0x0000};
	static int IData0Col[] = {0x07C0,0x1830,0x2388,0x4FE4,0x5FF4,0x9FF2,0xBFFA,0xBFFA,
							   0xBFFA,0x9FF2,0x5FF4,0x4FE4,0x2388,0x1830,0x07C0,0x0000,
							   0x07C0,0x1830,0x2388,0x4FE4,0x5FF4,0x9FF2,0xBFFA,0xBFFA,
							   0xBFFA,0x9FF2,0x5FF4,0x4FE4,0x2388,0x1830,0x07C0,0x0000,
							   0x07C0,0x1830,0x2388,0x4FE4,0x5FF4,0x9FF2,0xBFFA,0xBFFA,
							   0xBFFA,0x9FF2,0x5FF4,0x4FE4,0x2388,0x1830,0x07C0,0x0000,
							   0x07C0,0x1830,0x2018,0x401C,0x400C,0x800E,0x8006,0x8006,
							   0x8006,0x800E,0x400C,0x401C,0x2C78,0x1FF0,0x07C0,0x0000};
	static int SMask0Col[] = {0x07C0,0x1FF0,0x3FF8,0x7FFC,0x7FFC,0xFFFE,0xFFFE,0xFFFE,
							   0xFFFE,0xFFFE,0x7FFC,0x7FFC,0x3FF8,0x1FF0,0x07C0,0x0000};
	static int SData0Col[] = {0x07C0,0x1FF0,0x3FE8,0x7FE4,0x7FF4,0xFFF2,0xFFFA,0xFFFA,
							   0xFFFA,0xFFF2,0x7FF4,0x7FE4,0x3388,0x1830,0x07C0,0x0000,
							   0x07C0,0x1FF0,0x3FE8,0x7FE4,0x7C74,0xF832,0xF01A,0xF01A,
							   0xF01A,0xF832,0x7C74,0x7FE4,0x3388,0x1830,0x07C0,0x0000,
							   0x07C0,0x1FF0,0x3FE8,0x7FE4,0x7C74,0xF832,0xF01A,0xF01A,
							   0xF01A,0xF832,0x7C74,0x7FE4,0x3388,0x1830,0x07C0,0x0000,
							   0x07C0,0x1FF0,0x3C68,0x7004,0x6004,0xE002,0xC002,0xC002,
							   0xC002,0xE002,0x6004,0x7004,0x3008,0x1830,0x07C0,0x0000};
	static int IMask1Mon[] = {0x0FE0,0x7FFC,0xFFFE,0xFFFE,0xFFFE,0x7FFC,0x0FE0,0x0000};
	static int IData1Mon[] = {0x0FE0,0x701C,0x8002,0x8002,0x8002,0x701C,0x0FE0,0x0000};
	static int SMask1Mon[] = {0x0FE0,0x7FFC,0xFFFE,0xFFFE,0xFFFE,0x7FFC,0x0FE0,0x0000};
	static int SData1Mon[] = {0x0FE0,0x701C,0x87C2,0x9FF2,0x87C2,0x701C,0x0FE0,0x0000};
	static int IMask1Col[] = {0x0FE0,0x7FFC,0xFFFE,0xFFFE,0xFFFE,0x7FFC,0x0FE0,0x0000};
	static int IData1Col[] = {0x0FE0,0x701C,0x87C2,0xBFFA,0x87C2,0x701C,0x0FE0,0x0000,
							   0x0FE0,0x701C,0x87C2,0xBFFA,0x87C2,0x701C,0x0FE0,0x0000,
							   0x0FE0,0x701C,0x87C2,0xBFFA,0x87C2,0x701C,0x0FE0,0x0000,
							   0x0FE0,0x701C,0x8006,0x8006,0xB83E,0x7FFC,0x0FE0,0x0000};
	static int SMask1Col[] = {0x0FE0,0x7FFC,0xFFFE,0xFFFE,0xFFFE,0x7FFC,0x0FE0,0x0000};
	static int SData1Col[] = {0x0FE0,0x7FFC,0xFFFA,0xFFFA,0xC7C2,0x701C,0x0FE0,0x0000,
							   0x0FE0,0x7FFC,0xFC7A,0xF01A,0xC442,0x701C,0x0FE0,0x0000,
							   0x0FE0,0x7FFC,0xFC7A,0xF01A,0xC442,0x701C,0x0FE0,0x0000,
							   0x0FE0,0x7FFC,0xF83A,0xC002,0xC002,0x701C,0x0FE0,0x0000};
	static int IMask2Mon[] = {0x3800,0x7C00,0xFE00,0xFE00,0xFE00,0x7C00,0x3800,0x0000};
	static int IData2Mon[] = {0x3800,0x4400,0x8200,0x8200,0x8200,0x4400,0x3800,0x0000};
	static int SMask2Mon[] = {0x3800,0x7C00,0xFE00,0xFE00,0xFE00,0x7C00,0x3800,0x0000};
	static int SData2Mon[] = {0x3800,0x4400,0xBA00,0xBA00,0xBA00,0x4400,0x3800,0x0000};
	static int IMask2Col[] = {0x3800,0x7C00,0xFE00,0xFE00,0xFE00,0x7C00,0x3800,0x0000};
	static int IData2Col[] = {0x3800,0x4400,0xBA00,0xBA00,0xBA00,0x4400,0x3800,0x0000,
							   0x3800,0x4400,0xBA00,0xBA00,0xBA00,0x4400,0x3800,0x0000,
							   0x3800,0x4400,0xBA00,0xBA00,0xBA00,0x4400,0x3800,0x0000,
							   0x3800,0x4400,0x8600,0x8600,0x8600,0x7C00,0x3800,0x0000};
	static int SMask2Col[] = {0x3800,0x7C00,0xFE00,0xFE00,0xFE00,0x7C00,0x3800,0x0000};
	static int SData2Col[] = {0x3800,0x7C00,0xFA00,0xFA00,0xFA00,0x4400,0x3800,0x0000,
							   0x3800,0x7C00,0xC200,0xC200,0xC200,0x4400,0x3800,0x0000,
							   0x3800,0x7C00,0xC200,0xC200,0xC200,0x4400,0x3800,0x0000,
							   0x3800,0x7C00,0xC200,0xC200,0xC200,0x4400,0x3800,0x0000};
	static int *bufIMask = NULL,*bufIData = NULL;
	static int *bufSMask = NULL,*bufSData = NULL;
	static int width = 0,height = 0,planes = 0;
	static int col[2] = {WHITE,WHITE};
	int	vdiHandle,pxy[8];
	MFDB mfdb;
	int pxyarray[8];
	int disabled = pb->pb_tree[pb->pb_obj].ob_state & DISABLED;
	EXTINFO *ex = (EXTINFO *) pb->pb_parm;
	int obtype = ex->oldtype;
	char *unformatted = ex->te_ptext;
	int newx, newy;

	if (((obtype >> 8) == CUSTOM) && (pb->pb_tree[pb->pb_obj].ob_flags & RBUTTON)) {
		if (bufIMask == NULL) {
			ICONBLK	iconBlk;

			if ((bufIMask = malloc(32 * 2 * ((planes = (num_planes < 4 ? 1 : num_planes)) + 1))) != NULL) {
				bufSData = (bufSMask = (bufIData = bufIMask + 16) + 16 * planes) + 16;
				if (gr_ch == 16) {
					width  = iconBlk.ib_wicon =
					height = iconBlk.ib_hicon = 16;

					if (planes >= 4) {
						FixColIcon(&iconBlk,planes,IData0Col,IMask0Col,
						           bufIData,bufIMask,NULL,NULL,NULL);
						FixColIcon(&iconBlk,planes,SData0Col,SMask0Col,
						           bufSData,bufSMask,NULL,NULL,NULL);
					} else {
						FixColIcon(&iconBlk,planes,IData0Mon,IMask0Mon,
					    	       bufIData,bufIMask,NULL,NULL,NULL);
						FixColIcon(&iconBlk,planes,SData0Mon,SMask0Mon,
						           bufSData,bufSMask,NULL,NULL,NULL);
					}
				} else {
					int		workout[57];

					vq_extnd(VDIhandle,0,workout);
					if ((int)(((long)workout[3] * 100L) / (long)workout[4]) < 75) {
						width  = iconBlk.ib_wicon = 16;
						height = iconBlk.ib_hicon = 8;

						if (planes >= 4) {
							FixColIcon(&iconBlk,planes,IData1Col,IMask1Col,
							           bufIData,bufIMask,NULL,NULL,NULL);
							FixColIcon(&iconBlk,planes,SData1Col,SMask1Col,
							           bufSData,bufSMask,NULL,NULL,NULL);
						} else {
							FixColIcon(&iconBlk,planes,IData1Mon,IMask1Mon,
							           bufIData,bufIMask,NULL,NULL,NULL);
							FixColIcon(&iconBlk,planes,SData1Mon,SMask1Mon,
							           bufSData,bufSMask,NULL,NULL,NULL);
						}
					} else {
						width  = iconBlk.ib_wicon =
						height = iconBlk.ib_hicon = 8;
						if (planes >= 4) {
							FixColIcon(&iconBlk,planes,IData2Col,IMask2Col,
							           bufIData,bufIMask,NULL,NULL,NULL);
							FixColIcon(&iconBlk,planes,SData2Col,SMask2Col,
							           bufSData,bufSMask,NULL,NULL,NULL);
						} else {
							FixColIcon(&iconBlk,planes,IData2Mon,IMask2Mon,
							           bufIData,bufIMask,NULL,NULL,NULL);
							FixColIcon(&iconBlk,planes,SData2Mon,SMask2Mon,
							           bufSData,bufSMask,NULL,NULL,NULL);
						}
					}
				}
			}
		}
	}

	newx = (pb->pb_x + (pb->pb_w / 2));
	newy = (pb->pb_y + (pb->pb_h / 2));

	newx -= (image_w / 2);
	newy -= (image_h / 2);

	switch (obtype >> 8) {
		case CUSTOM:
			if (pb->pb_tree[pb->pb_obj].ob_flags & RBUTTON) {
				pxy[0] = pxy[1] = 0;
				pxy[6] = (pxy[4] = pb->pb_x + 16 - width) + (pxy[2] = width  - 1);
				pxy[7] = (pxy[5] = pb->pb_y             ) + (pxy[3] = height - 1);
				mfdb.fd_addr	= pb->pb_currstate & SELECTED ?
	    			              bufSMask : bufIMask;
				mfdb.fd_w		= width;
				mfdb.fd_h		= height;
				mfdb.fd_wdwidth	= 1;
				mfdb.fd_stand	= 1;
				mfdb.fd_nplanes	= 1;
				mfdb.fd_r1		=
				mfdb.fd_r2		=
				mfdb.fd_r3		= 0;

				vrt_cpyfm(VDIhandle,MD_TRANS,pxy,&mfdb,&screen,col);

				mfdb.fd_addr	= pb->pb_currstate & SELECTED ?
				                  bufSData : bufIData;
				mfdb.fd_nplanes	= planes;
			}

			if (pb->pb_tree[pb->pb_obj].ob_flags & RBUTTON) {
				if (planes > 1) {
					mfdb.fd_stand	= 0;
					vro_cpyfm(VDIhandle,num_planes > 8 ? S_AND_D : S_OR_D,
		    	    		  pxy,&mfdb,&screen);
				} else {
					if ((pb->pb_currstate & SELECTED) && !disabled)
						vrt_copy(radio_on, pb, 1, 0);
					else
						vrt_copy(radio_off, pb, 1, 0);
				}
			} else
				if ((pb->pb_currstate & SELECTED) && !disabled)
					vrt_copy(box_on, pb, 1, 0);
				else
					vrt_copy(box_off, pb, 1, 0);

			vsl_color(VDIhandle, 1);
			pb->pb_currstate &= ~SELECTED;

/*			pb_doobject(pb, 3 * gr_cw, 0); */
			pb_doobject(pb, 0, 0);
			break;

		case CYCLEBTN:
			pb_doobject(pb, 0, 0);

			pb->pb_x = newx;
			pb->pb_y = newy;

			if (pb->pb_currstate & SELECTED)
				vrt_copy(cycle_on, pb, 1, 0);
			else
				vrt_copy(cycle_off, pb, 1, 0);

			pb->pb_currstate &= ~SELECTED;
			break;

		case DROPDOWN:
			pb_doobject(pb, 0, 0);

			pb->pb_x = newx;
			pb->pb_y = newy;

			if (pb->pb_currstate & SELECTED)
				vrt_copy(dropdown_on, pb, 1, 0);
			else
				vrt_copy(dropdown_off, pb, 1, 0);

			pb->pb_currstate &= ~SELECTED;
			break;

		case CUSTBTN:
			switch(*unformatted) {
				case '\001':
					pb_doobject(pb, 0, 0);

					pb->pb_x = newx;
					pb->pb_y = newy;

					if (pb->pb_currstate & SELECTED)
						vrt_copy(up_on, pb, 1, 0);
					else
						vrt_copy(up_off, pb, 1, 0);

					pb->pb_currstate &= ~SELECTED;
					break;

				case '\002':
					pb_doobject(pb, 0, 0);

					pb->pb_x = newx;
					pb->pb_y = newy;

					if (pb->pb_currstate & SELECTED)
						vrt_copy(down_on, pb, 1, 0);
					else
						vrt_copy(down_off, pb, 1, 0);

					pb->pb_currstate &= ~SELECTED;
					break;

				case '\003':
					pb_doobject(pb, 0, 0);

					pb->pb_x = newx;
					pb->pb_y = newy;

					if (pb->pb_currstate & SELECTED)
						vrt_copy(right_on, pb, 1, 0);
					else
						vrt_copy(right_off, pb, 1, 0);

					pb->pb_currstate &= ~SELECTED;
					break;

				case '\004':
					pb_doobject(pb, 0, 0);

					pb->pb_x = newx;
					pb->pb_y = newy;

					if (pb->pb_currstate & SELECTED)
						vrt_copy(left_on, pb, 1, 0);
					else
						vrt_copy(left_off, pb, 1, 0);

					pb->pb_currstate &= ~SELECTED;
					break;
			}
			break;
	}

/*	return pb->pb_currstate | disabled; */
	return(pb->pb_currstate & ~(SELECTED|SHADOWED|(num_planes < 4 ? 0 : DISABLED)));
}

/*
 *	Userdefined menuline function
 */
LOCAL int cdecl draw_menuline(PARMBLK *pb)
{
	int attr[10], fillattr[5], lineattr[6], pxyarray[6];
	GRECT line1, line2;

	vqt_attributes(VDIhandle, attr);
	vqf_attributes(VDIhandle, fillattr);
	vql_attributes(VDIhandle, lineattr);

	pxyarray[0] = pb->pb_xc;
	pxyarray[1] = pb->pb_yc;
	pxyarray[2] = pb->pb_xc + pb->pb_wc - 1;
	pxyarray[3] = pb->pb_yc + pb->pb_hc - 1;
	vs_clip(VDIhandle, 1, pxyarray);

	line1.g_x = line2.g_x = pb->pb_x;
	line1.g_y = line1.g_h = pb->pb_y + (pb->pb_h / 2) - 1;
	line1.g_w = line2.g_w = pb->pb_x + pb->pb_w - 1;
	line2.g_y = line2.g_h = pb->pb_y + (pb->pb_h / 2);

	vsl_color(VDIhandle, ((EXTINFO *) pb->pb_parm)->te_color.bord_color);

	if (pb->pb_tree[pb->pb_obj].ob_state & DISABLED) {
		vsl_type(VDIhandle, 7);
		vsl_udsty(VDIhandle, 0xAAAA);
		line(line1.g_x, line1.g_y, line1.g_w, line1.g_h);

		vsl_udsty(VDIhandle, 0x5555);
		line(line2.g_x, line2.g_y, line2.g_w, line2.g_h);
	} else {
		line(line1.g_x, line1.g_y, line1.g_w, line1.g_h);
		line(line2.g_x, line2.g_y, line2.g_w, line2.g_h);
	}

	vst_color(VDIhandle, attr[1]);
	vswr_mode(VDIhandle, attr[5]);

	vsf_color(VDIhandle, fillattr[1]);
	vsf_interior(VDIhandle, fillattr[0]);
	vsf_style(VDIhandle, fillattr[2]);

	vsl_color(VDIhandle, lineattr[1]);
	vsl_type(VDIhandle, 7);
	vsl_udsty(VDIhandle, 0xFFFF);

	return FALSE;
}

/*
 *	Userdefined menu effects
 */
LOCAL int cdecl draw_menueffects(PARMBLK *pb)
{
	int attr[10], fillattr[5], lineattr[6], effects = 0, pxyarray[6];
	EXTINFO *ex = (EXTINFO *) pb->pb_parm;
	int pxy[8];

	if (pb->pb_currstate & 0x100) effects |= 1;
	if (pb->pb_currstate & 0x200) effects |= 8;
	if (pb->pb_currstate & 0x400) effects |= 4;
	if (pb->pb_currstate & 0x800) effects |= 2;
	if (pb->pb_currstate & 0x1000) effects |= 16;

	vst_effects(VDIhandle, effects);
	v_gtext(VDIhandle, pb->pb_x, pb->pb_y, ex->te_ptext);

	if (pb->pb_currstate & SELECTED) {
		vswr_mode(VDIhandle, MD_XOR);
		pxy[0] = pb->pb_x;
		pxy[1] = pb->pb_y;
		pxy[2] = pb->pb_x + pb->pb_w - 1;
		pxy[3] = pb->pb_y + pb->pb_h - 1;

		vsf_color(VDIhandle, BLACK);
		vr_recfl(VDIhandle, pxy);
	}
	return FALSE;
}

LOCAL int cdecl DrawColIcon(PARMBLK *parmBlk)
{
	static int		col[2] = {-1,0};
	static char		letter[] = " ";
	MFDB			mfdb;
	int				pxy[8], clip[8];
	long			bitPlaneSize;
	char			*addr;
	short			*image,*mask,*selImage,*selMask;
	ICONBLK			*iconBlk;
	int				vdiHandle,planeCount,i,imageCol,maskCol;

	vdiHandle = VDIhandle;
	addr	= (char *)parmBlk->pb_parm;
	iconBlk	= (ICONBLK *)addr;
	planeCount = (int)(long)iconBlk->ib_pdata;
	bitPlaneSize = sizeof(short) * ((iconBlk->ib_wicon + 15) / 16L) * (long)iconBlk->ib_hicon;

	image   = (short *)(addr += sizeof(ICONBLK));
	mask    = (short *)(addr += planeCount * bitPlaneSize);
	selImage= (short *)(addr +=              bitPlaneSize);
	selMask = (short *)(addr += planeCount * bitPlaneSize);

	if (parmBlk->pb_currstate & SELECTED) {
		image    = selImage;
		mask     = selMask;
		imageCol = (iconBlk->ib_char >>  8) & 0xf;
		maskCol  = (iconBlk->ib_char >> 12) & 0xf;
	} else {
		imageCol = (iconBlk->ib_char >> 12) & 0xf;
		maskCol  = (iconBlk->ib_char >>  8) & 0xf;
	}

	clip[0] = parmBlk->pb_xc;
	clip[1] = parmBlk->pb_yc;
	clip[2] = parmBlk->pb_wc;
	clip[3] = parmBlk->pb_hc;
	vs_clip(vdiHandle, 1, clip);

	if (intersect(0,0,parmBlk->pb_w,parmBlk->pb_h,
	                iconBlk->ib_xicon,iconBlk->ib_yicon,
	                iconBlk->ib_wicon,iconBlk->ib_hicon,
	                pxy+4,pxy+5,pxy+6,pxy+7)) {
		pxy[0] = pxy[1] = 0;
		pxy[2] = pxy[6]-= 1;
		pxy[3] = pxy[7]-= 1;
		pxy[6]+= pxy[4]+= parmBlk->pb_x;
		pxy[7]+= pxy[5]+= parmBlk->pb_y;
		mfdb.fd_addr	= mask;
		mfdb.fd_w		= iconBlk->ib_wicon;
		mfdb.fd_h		= iconBlk->ib_hicon;
		mfdb.fd_wdwidth	= (iconBlk->ib_wicon + 15) / 16;
		mfdb.fd_stand	= 1;
		mfdb.fd_nplanes	= 1;
		mfdb.fd_r1		=
		mfdb.fd_r2		=
		mfdb.fd_r3		= 0;
		col[0]          = planeCount == 1 ||
		                  ((iconBlk->ib_char & 0xf00) != 0x100) ?
		                  (iconBlk->ib_char >> 8) & 0xf : WHITE;

		vrt_cpyfm(vdiHandle,MD_TRANS,pxy,&mfdb,&screen,col);
		mfdb.fd_addr	= image;
		mfdb.fd_nplanes	= planeCount;
		if (planeCount > 1) {
			mfdb.fd_stand	= 0;
			vro_cpyfm(vdiHandle,num_planes > 8 ? S_AND_D : S_OR_D,
			          pxy,&mfdb,&screen);
		} else {
			col[0]      = (iconBlk->ib_char >> 12) & 0xf;
			vrt_cpyfm(vdiHandle,MD_TRANS,pxy,&mfdb,&screen,col);
		}
	}

	if (iconBlk->ib_ptext[0]) {
		pxy[2] = (pxy[0] = parmBlk->pb_x + iconBlk->ib_xtext) +
		         iconBlk->ib_wtext - 1;
		pxy[3] = (pxy[1] = parmBlk->pb_y + iconBlk->ib_ytext) +
		         iconBlk->ib_htext - 1;

		vswr_mode(vdiHandle,MD_REPLACE);
		vsf_color(vdiHandle,maskCol);
		vsf_interior(vdiHandle,FIS_SOLID);
		vsf_perimeter(vdiHandle,0);
		v_bar(vdiHandle,pxy);
	}

	if ((letter[0] = iconBlk->ib_char) != '\000' || iconBlk->ib_ptext[0]) {
		vswr_mode(vdiHandle,MD_TRANS);
		vst_font(vdiHandle,1);
		vst_height(vdiHandle,4,&i,&i,&i,&i);
		vst_color(vdiHandle,imageCol);
		vst_effects(vdiHandle,0);
		vst_alignment(vdiHandle,0,5,&i,&i);
		vst_rotation(vdiHandle,0);
		if (iconBlk->ib_ptext[0])
			v_gtext(vdiHandle,pxy[0]+(iconBlk->ib_wtext-
			        (int)strlen(iconBlk->ib_ptext)*6)/2,
					pxy[1]+(iconBlk->ib_htext-6)/2,iconBlk->ib_ptext);
		if (letter[0])
			v_gtext(vdiHandle,parmBlk->pb_x+iconBlk->ib_xicon+
			        iconBlk->ib_xchar,parmBlk->pb_y+iconBlk->ib_yicon+
			        iconBlk->ib_ychar,letter);
	}

	return(parmBlk->pb_currstate & ~SELECTED);
}

/*
 *	Fix resource objects to include customised objects
 *
 *	*obj = pointer to object to fix
 *
 *	Returns: TRUE on success
 */
GLOBAL int fix_object(OBJECT *obj, int sizefix)
{
	int images = DARK_SCALING | SCALING, object = 0;
	USERBLK *ub;

	do {
		object++;

		if (!(obj[object].ob_flags & MENUSIDE) && ((obj[object].ob_type & 0x0F) != G_TITLE)) {
		switch (obj[object].ob_type & 0xff) {
			case G_ICON:
				if ((obj->ob_type >> 8) == SCALE) {
					ICONBLK *icn = obj[object].ob_spec.iconblk;

					trans_image(obj);
					scale_image(obj, images);
					obj[object].ob_height = icn->ib_ytext + icn->ib_htext;
				}
				break;

			case G_IMAGE:
				if ((obj[object].ob_type >> 8) == SCALE) {
					trans_image(obj);
					scale_image(obj, images);
					obj[object].ob_height = obj[object].ob_spec.bitblk->bi_hl;
				}
				break;

			case G_CICON:
				obj[object].ob_spec.userblk->ub_parm = (long) obj[object].ob_spec.iconblk;
				obj[object].ob_spec.userblk->ub_code = DrawColIcon;
				obj[object].ob_type = G_USERDEF;
				break;

			default:
				if (((obj[object].ob_type >> 8)==UNDERLINE) ||
					((obj[object].ob_type >> 8)==CUSTOM) ||
					((obj[object].ob_type >> 8)==CYCLEBTN) ||
					((obj[object].ob_type >> 8)==BOXFRAME) ||
					((obj[object].ob_type >> 8)==CUSTBTN) ||
					((obj[object].ob_type >> 8)==DROPDOWN) ||
					((obj[object].ob_type >> 8)==MENULINE) ||
					(obj[object].ob_state & DRAW3D)) {
						if (ub = calloc(1, sizeof(USERBLK) + sizeof(EXTINFO))) {
							EXTINFO *ex = (EXTINFO *) (ub + 1);

							switch(obj[object].ob_type & 0xff) {
								case G_TEXT:
									memcpy(ex, obj[object].ob_spec.tedinfo, sizeof(TEDINFO));
									ex->te_thickness = 0;
									break;

								case G_BOXTEXT:
									memcpy(ex, obj[object].ob_spec.tedinfo, sizeof(TEDINFO));

									if (ex->te_thickness < 0) {
										obj[object].ob_width -= ex->te_thickness * 2;
										obj[object].ob_height -= ex->te_thickness * 2;
										obj[object].ob_x += ex->te_thickness;
										obj[object].ob_y += ex->te_thickness;
									}
									break;

								case G_STRING:
									ex->te_ptext = obj[object].ob_spec.free_string;
									ex->te_font = 3;
									ex->te_color.bord_color = ex->te_color.text_color = 1;
									ex->te_thickness = 0;
									break;

								case G_BUTTON:
									ex->te_ptext = obj[object].ob_spec.free_string;
									ex->te_font = 3;
									ex->te_just = 2;
									ex->te_thickness = obj[object].ob_flags & EXIT ? (obj[object].ob_flags & DEFAULT ? -3 : -2) : -1;
									ex->te_color.bord_color = ex->te_color.text_color = 1;

									if (ex->te_thickness < 0) {
										obj[object].ob_width -= ex->te_thickness * 2;
										obj[object].ob_height -= ex->te_thickness * 2;
										obj[object].ob_x += ex->te_thickness;
										obj[object].ob_y += ex->te_thickness;
									}
									break;

								case G_BOX:
									ex->te_ptext = "";
									ex->te_font = 3;
									ex->te_just = 2;
									ex->te_thickness = obj[object].ob_spec.obspec.framesize;
									ex->te_color.bord_color = obj[object].ob_spec.obspec.framecol;
									ex->te_color.text_color = obj[object].ob_spec.obspec.textcol;
									ex->te_color.in_color = obj[object].ob_spec.obspec.interiorcol;
									ex->te_color.fill_ptn = obj[object].ob_spec.obspec.fillpattern;
									if (ex->te_color.fill_ptn == 1)
										ex->te_color.fill_ptn = 0;

									if (ex->te_thickness < 0) {
										obj[object].ob_width -= ex->te_thickness * 2;
										obj[object].ob_height -= ex->te_thickness * 2;
										obj[object].ob_x += ex->te_thickness;
										obj[object].ob_y += ex->te_thickness;
									}
									break;

								case G_IBOX:
									ex->te_ptext = "";
									ex->te_font = 3;
									ex->te_just = 2;
									ex->te_thickness = obj[object].ob_spec.obspec.framesize;
									ex->te_color.bord_color = obj[object].ob_spec.obspec.framecol;
									ex->te_color.text_color = obj[object].ob_spec.obspec.textcol;
									ex->te_color.in_color = obj[object].ob_spec.obspec.interiorcol;
									ex->te_color.fill_ptn = 0;

									if (ex->te_thickness < 0) {
										obj[object].ob_width -= ex->te_thickness * 2;
										obj[object].ob_height -= ex->te_thickness * 2;
										obj[object].ob_x += ex->te_thickness;
										obj[object].ob_y += ex->te_thickness;
									}
									break;

								case G_BOXCHAR:
									ex->te_ptext = "X";
									*ex->te_ptext = obj[object].ob_spec.obspec.character;
									ex->te_font = 3;
									ex->te_just = 2;
									ex->te_thickness = obj[object].ob_spec.obspec.framesize;
									ex->te_color.bord_color = obj[object].ob_spec.obspec.framecol;
									ex->te_color.text_color = obj[object].ob_spec.obspec.textcol;
									ex->te_color.in_color = obj[object].ob_spec.obspec.interiorcol;
									ex->te_color.fill_ptn = obj[object].ob_spec.obspec.fillpattern;
									if (ex->te_color.fill_ptn == 1)
										ex->te_color.fill_ptn = 0;

									if (ex->te_thickness < 0) {
										obj[object].ob_width -= ex->te_thickness * 2;
										obj[object].ob_height -= ex->te_thickness * 2;
										obj[object].ob_x += ex->te_thickness;
										obj[object].ob_y += ex->te_thickness;
									}
									break;

								default:
									break;
							}

							ex->oldparm = obj[object].ob_spec.userblk;
							ex->oldtype = obj[object].ob_type;

							ub->ub_parm = (long) ex;

							if (((obj[object].ob_state & DRAW3D) || (obj[object].ob_state & MENUTYPE)) &&
								((obj[object].ob_type >> 8)!=BOXFRAME) &&
								((obj[object].ob_type >> 8)!=UNDERLINE) &&
								((obj[object].ob_type >> 8)!=CUSTOM) &&
								((obj[object].ob_type >> 8)!=CYCLEBTN) &&
								((obj[object].ob_type >> 8)!=CUSTBTN) &&
								((obj[object].ob_type >> 8)!=MENULINE) &&
								((obj[object].ob_type >> 8)!=DROPDOWN)) {
								char *ptr;		/* are put in the upper 8 bits of ob_type! */

								ub->ub_code = draw_specialtext;

								if (((obj[object].ob_type >> 8) != FLYING))
									if ((ptr = strchr(ex->te_ptext, '[')) && *(++ptr))
										obj[object].ob_type = G_USERDEF | ((toupper(*ptr) & 0x7f) << 8);
									else
										obj[object].ob_type = G_USERDEF;
								else
									obj[object].ob_type = (((obj[object].ob_type >> 8) & 0xFF) << 8) + G_USERDEF;
							}

							switch (obj[object].ob_type >> 8) {
								case UNDERLINE:
									ub->ub_code = draw_underline;
									obj[object].ob_type = (UNDERLINE << 8) + G_USERDEF;
									break;

								case BOXFRAME:
									ub->ub_code = draw_boxframe;
									obj[object].ob_type = (BOXFRAME << 8) + G_USERDEF;
									break;

								case MENULINE:
									ub->ub_code = draw_menuline;
									obj[object].ob_type = (MENULINE << 8) + G_USERDEF;
									break;

								case CUSTOM:
								case CYCLEBTN:
								case DROPDOWN:
								case CUSTBTN: {
										char *ptr = ex->te_ptext;
										int chars = 3;
		
										while (*ptr)
											if (*ptr++ != '[')
												chars++;
										if (((obj[object].ob_type >> 8) != CYCLEBTN) &&
											((obj[object].ob_type >> 8) != DROPDOWN) &&
											((obj[object].ob_type >> 8) != CUSTBTN))
											obj[object].ob_width = (chars) * gr_cw;

										ub->ub_code = draw_custbutton;
										if ((obj[object].ob_type >> 8) == CUSTOM)
											if ((ptr = strchr(ex->te_ptext, '[')) && *(++ptr))
												obj[object].ob_type = G_USERDEF | ((toupper(*ptr) & 0x7f) << 8) | 0x8000;
											else
												obj[object].ob_type = G_USERDEF | 0x8000;
										else {
											if ((obj[object].ob_type >> 8) == CYCLEBTN)
												obj[object].ob_type = (CYCLEBTN << 8) + G_USERDEF;
											if ((obj[object].ob_type >> 8) == DROPDOWN)
												obj[object].ob_type = (DROPDOWN << 8) + G_USERDEF;
											if ((obj[object].ob_type >> 8) == CUSTBTN)
												obj[object].ob_type = (CUSTBTN << 8) + G_USERDEF;
										}
									}
									break;
							}

							if (AES_VERSION >= 0x0400)
								if (obj[object].ob_state & DRAW3D) {
									if ((ex->oldtype & G_BUTTON) ||
										(ex->oldtype & G_BOXTEXT)) {
										if (ex->te_thickness > 0) {
											obj[object].ob_x -= (abs(ex->te_thickness));
											obj[object].ob_y -= (abs(ex->te_thickness));
											obj[object].ob_width += (abs(ex->te_thickness)) * 2;
											obj[object].ob_height += (abs(ex->te_thickness)) * 2;
										}

										if (ex->te_thickness < 0) {
											obj[object].ob_x += (abs(ex->te_thickness));
											obj[object].ob_y += (abs(ex->te_thickness));
											obj[object].ob_width -= (abs(ex->te_thickness)) * 2;
											obj[object].ob_height -= (abs(ex->te_thickness)) * 2;
										}
									}
/*									obj[object].ob_x += 1;
									obj[object].ob_y += 1;
									obj[object].ob_width -= 2;
									obj[object].ob_height -= 2; */
								}

							obj[object].ob_spec.userblk = ub;
						} else
							return FALSE;
				}
			}
		}
	} while(!(obj[object].ob_flags & LASTOB));

	if (sizefix)
		position_fix(obj);

	return TRUE;
}



/*
 *	Restore ("unfix") objects to normal
 *
 *	*obj = pointer to object to unfix
 *
 *	Returns: nothing
 */
GLOBAL void unfix_object(OBJECT *obj)
{
	USERBLK *ub;
	EXTINFO *ex;

	if (obj->ob_type != G_TITLE) {
		if (((obj->ob_type >> 8)==UNDERLINE) ||
			((obj->ob_type >> 8)==CUSTOM) ||
			(obj->ob_state & DRAW3D)) {
				ub = obj->ob_spec.userblk;
				ex = (EXTINFO *) ub->ub_parm;

				if (ex != NULL) {
					if (ex->te_thickness < 0) {
						obj->ob_width += ex->te_thickness * 2;
						obj->ob_height += ex->te_thickness * 2;
						obj->ob_x -= ex->te_thickness;
						obj->ob_y -= ex->te_thickness;
					}

					obj->ob_spec.userblk = ex->oldparm;
					obj->ob_type = ex->oldtype;
					free(ub);
				}
		}
	}
}


/*
 *	Initialise images
 *
 *	Returns: nothing
 */
GLOBAL void init_images(void)
{
	set_images(&radios, &radio_on, &radio_off);
	set_images(&checks, &box_on, &box_off);
	set_images(&cycles, &cycle_on, &cycle_off);
	set_images(&uparrow, &up_on, &up_off);
	set_images(&dnarrow, &down_on, &down_off);
	set_images(&lfarrow, &left_on, &left_off);
	set_images(&rtarrow, &right_on, &right_off);
	set_images(&dropdown, &dropdown_on, &dropdown_off);
}