Ejemplo n.º 1
0
int closest (struct surface *current_surface, struct leaf *lf, double pnt[3])
{
	int j, k, jmin, nch;
	double dmin;
	double dta[MAXPA];
	double several_centers[MAXPA][3], several_radii[MAXPA];
    struct cept *ex;

	if (lf -> type == SPHERE && lf -> shape == CONVEX) nch = 1;
	else if (lf -> shape == SADDLE) nch = 2;
	else if (lf -> type == SPHERE && lf -> shape == CONCAVE) nch = 3;
	else if (lf -> type == CYLINDER) nch = 2;
	else if (lf -> type == TORUS && lf -> shape == CONVEX) nch = 1;
	else {
		ex = new_cept (LOGIC_ERROR,  NOT_FOUND,  FATAL_SEVERITY);
		add_function (ex, "closest");
		add_source (ex, "msrender.c");
        add_long (ex, "leaf type", (long) lf -> type);
        add_long (ex, "leaf shape", (long) lf -> shape);
		return(0);
	}

	if (nch <= 1)
		return (lf -> atmnum[0]);

	if (lf -> atmnum[3] > 0)
		nch = 4;
	for (j = 0; j < nch; j++) {
		for (k = 0; k < 3; k++)
			several_centers[j][k] = *(current_surface -> atom_centers + 3 * (lf -> atmnum[j] - 1) + k);
		several_radii[j] = *(current_surface -> atom_radii + (lf -> atmnum[j] - 1));
	}

	/* find closest atom */

	for (j = 0; j < nch; j++)
		dta[j] = distance (pnt, several_centers[j]) - several_radii[j];

	/* initialization */
	dmin = 1000000.0;
	jmin = -1;

	for (j = 0; j < nch; j++)
		if (dta[j] < dmin) {
			dmin = dta[j];
			jmin = j;
		}

	if (jmin < 0 || jmin >= nch) {
		ex = new_cept (LOGIC_ERROR,  NOT_FOUND,  FATAL_SEVERITY);
		add_function (ex, "closest");
		add_source (ex, "msrender.c");
		add_message (ex, "cannot find closest atom");
		return (0);
	}
	return (lf -> atmnum[jmin]);
}
Ejemplo n.º 2
0
  Element::
  Element (::XSCRT::XML::Element< wchar_t > const& e)
  :Base (e), regulator__ ()
  {

    ::XSCRT::Parser< wchar_t > p (e);

    while (p.more_elements ())
    {
      ::XSCRT::XML::Element< wchar_t > e (p.next_element ());
      ::std::basic_string< wchar_t > n (::XSCRT::XML::uq_name (e.name ()));

      if (n == L"value")
      {
        ::XMLSchema::string< wchar_t >::_ptr t (new ::XMLSchema::string< wchar_t > (e));
        add_value (t);
      }

      else if (n == L"long")
      {
        ::XMLSchema::long_::_ptr t (new ::XMLSchema::long_ (e));
        add_long (t);
      }

      else if (n == L"el")
      {
        ::Recursive::Element::_ptr t (new ::Recursive::Element (e));
        add_el (t);
      }

      else
      {
      }
    }
  }
Ejemplo n.º 3
0
void breakpoint_Relocation::set_target(address x) {
  assert(settable(), "must be settable");
  jint target_bits = (jint)internal() ? scaled_offset           (x)
				: runtime_address_to_index(x);
  short* p = &live_bits() + 1;
  add_long(p, target_bits);
  assert(p == instrs(), "new target must fit");
  _target = x;
}
Ejemplo n.º 4
0
static void
create() 
{
    ::create();
    set_race("fly");
    set_name("fly");
    add_long("It is flying around in circles.");
    scale_level(1, 3);
    scale_dex(8, 10);
    scale_ac(0, 2);
    scale_wc(1, 2);
    set_al(0);
    setmin("flies in");
    setmout("flies");
    add_property("unarmed_damage_type",({ "blunt" }));
Ejemplo n.º 5
0
static void
create() 
{
    ::create();
    set_name("skeleton");
    add_long("It is tattered with dried flesh.");
    scale_level(14, 17);
    scale_hp(250, 325);
    scale_wc(28, 32);
    scale_ac(4, 7);
    set_al(-500);
    set_aggressive(1);
    setmin("stumbles in");
    setmout("stumbles");
    add_money(random(600));
    add_property("unarmed_damage_type", ({ "claw", "bite" }));
Ejemplo n.º 6
0
void render_surface (struct msscene *ms, struct surface *current_surface)
{
	int is_vdw, type;
	double fine_pixel;
	char message[MAXLINE];
	struct face *fac;
	struct variety *vty;
    struct cept *ex;

	fine_pixel = ms -> pixel_width / ms -> fineness;
	is_vdw = (current_surface -> type == PQMS_SURFACE && current_surface -> probe_radius <= 0.0);

	for (fac = current_surface -> head_face; fac != NULL; fac = fac -> next) {
		vty = fac -> vty;
		if (fac -> problem) {
			sprintf (message,"skip problem face of atoms %5d %5d %5d %5d",
				vty -> atmnum[0], vty -> atmnum[1], vty -> atmnum[2], vty -> atmnum[3]);
			inform(message);
			continue;
		}
		if (is_vdw && (fac -> shape == CONCAVE || fac -> shape == SADDLE))
			continue;
		type = (int) vty -> type;
		switch (type) {
		case SPHERE:
			slice_sphere (ms, current_surface, fine_pixel, fac);
			break;
		case TORUS:
			slice_torus (ms, current_surface, fine_pixel, current_surface -> probe_radius, fac);
			break;
		case CYLINDER:
			slice_cylinder (ms, current_surface, fine_pixel, fac);
			break;
		default:
			ex = new_cept (ENUM_ERROR,  INVALID_VALUE,  FATAL_SEVERITY);
			add_function (ex, "render_surface");
			add_source (ex, "msrender.c");
            add_long (ex, "variety type", (long) type);
			return;
		}
		if (error()) return;
	}
}
Ejemplo n.º 7
0
int breakpoint_Relocation::pack_data() {
  short* p = data();

  assert(p == &live_bits(), "initializing live_bits");
  *p++ = _bits;

  jint target_bits = (jint) internal() ? scaled_offset           (_target)
				: runtime_address_to_index(_target);
  if (settable()) {
    // save space for set_target later
    add_long(p, target_bits);
  } else {
    add_int (p, target_bits);
  }

  for (int i = 0; i < instrlen(); i++) {
    add_short(p, (short)0x7777);    // placeholder value until bytes can be saved
  }

  return p - data();
}
Ejemplo n.º 8
0
/*
 * Put a simple element (basic class) onto a dialog template in memory.
 * return a pointer to where the next item should be added.
 *
 * parameters:
 *  lStyle = additional style flags
 *  x,y = x & y positions IN DIALOG UNITS
 *  w,h = width and height IN DIALOG UNITS
 *  Id	= ID used in messages
 *  clss  = class ID, e.g 0x80 for a button, 0x82 for a static
 *  caption = usually text or resource name
 *
 *  TODO: use the length information noted here to enable the dialog creation
 *  routines to work out more exactly how much memory they need to alloc.
 */
    static LPWORD
add_dialog_element(
    LPWORD p,
    DWORD lStyle,
    WORD x,
    WORD y,
    WORD w,
    WORD h,
    WORD Id,
    BYTE clss,
    const char *caption)
{

    lStyle = lStyle | WS_VISIBLE | WS_CHILD;

    add_word(x);
    add_word(y);
    add_word(w);
    add_word(h);
    add_word(Id);
    add_long(lStyle);
    add_byte(clss);
    if (((lStyle & SS_ICON) != 0) && (clss == 0x82))
    {
	/* Use resource ID */
	add_byte(0xff);
	add_byte(*caption);
    }
    else
	add_string(caption);

    add_byte(0);    //# of extra bytes following


    return p;
}
Ejemplo n.º 9
0
/* create tori */
void create_tori (struct surface *this_srf)
{
	int k;
	long n_pair;
	double root1, root2, distance12, squared_distance12;
	double radius1, radius2, torus_radius;
	double axis[3];
	double *sphere1_center, *sphere2_center;
	char message[MAXLINE];
	struct sphere *sphere1, *sphere2;
	struct neighbor *first_neighbor, *last_neighbor, *neighbor;
	struct neighbor *first_neighbor2, *last_neighbor2, *neighbor2;
	struct pair *pair_ptr;
    struct cept *ex;

	if (this_srf -> n_pair <= 0) return;

	/* initialize to tmp tor array beginning */
	pair_ptr = this_srf -> pair_array;
	n_pair = 0;

	/* loop through sphere list */
	for (sphere1 = (struct sphere *) (this_srf -> head_atom); sphere1 != NULL;
		sphere1 = sphere1 -> next) {
		if ((first_neighbor = sphere1 -> first_neighbor) == NULL) continue;
		last_neighbor = sphere1 -> last_neighbor;
		/* transfer info to local variables */
		sphere1_center = sphere1 -> center;
		radius1 = sphere1 -> radius;
		/* loop through neighbors of this sphere */
		for (neighbor = first_neighbor; neighbor <= last_neighbor;
			neighbor++) {
			sphere2 = neighbor -> sphptr;
			if (sphere1 >= sphere2) continue; /* no duplication */
			/* transfer info to local variables */
			sphere2_center = sphere2 -> center;
			radius2 = sphere2 -> radius;
			/* geometric computations for torus */
			for (k = 0; k < 3; k++)
				axis[k] = *(sphere2_center + k) - *(sphere1_center + k);
			distance12 = norm (axis);
			if (distance12 <= 0.0) {
				ex = new_cept (GEOMETRY_ERROR,  DEGENERACY,  FATAL_SEVERITY);
				add_function (ex, "create_tori");
				add_source (ex, "mstorus.c");
				add_message (ex, "coincident atoms");
				add_atom (ex, sphere1);
				add_atom (ex, sphere2);
				return;
			}
			squared_distance12 = distance12 * distance12;
			if (squared_distance12 <= 0.0) {
				ex = new_cept (GEOMETRY_ERROR,  DEGENERACY,  FATAL_SEVERITY);
				add_function (ex, "create_tori");
				add_source (ex, "mstorus.c");
				add_message (ex, "coincident atoms");
				add_atom (ex, sphere1);
				add_atom (ex, sphere2);
				return;
			}
			root1 = (radius1 + radius2 + 2 * this_srf -> probe_radius) *
				(radius1 + radius2 + 2 * this_srf -> probe_radius) -
				squared_distance12;
			if (root1 < 0.0) continue; /* sphere too far away */
			root1 = sqrt (root1);
			root2 = squared_distance12 - (radius1 - radius2) * (radius1 - radius2);
			if (root2 < 0.0) continue; /* one sphere inside other */
			root2 = sqrt (root2);
			torus_radius = 0.5 * root1 * root2 / distance12;
			if (torus_radius <= 0.0) continue;
			/* store pointer for torus in first spheres list */
			neighbor -> torptr = pair_ptr;
			/* store pointer for torus in second spheres list */
			first_neighbor2 = sphere2 -> first_neighbor;
			last_neighbor2 = sphere2 -> last_neighbor;
			for (neighbor2 = first_neighbor2;
				neighbor2 <= last_neighbor2; neighbor2++)
				if (neighbor2 -> sphptr == sphere1) {
					neighbor2 -> torptr = pair_ptr;
					break;
				}
			pair_ptr -> free = TRUE;
			pair_ptr -> buried = TRUE;
			pair_ptr -> sph[0] = sphere1;
			pair_ptr -> sph[1] = sphere2;
			pair_ptr++;
			n_pair = pair_ptr - this_srf -> pair_array;
			if (n_pair > this_srf -> n_pair) {
				ex = new_cept (LOGIC_ERROR,  INCONSISTENCY,  FATAL_SEVERITY);
				add_function (ex, "create_tori");
				add_source (ex, "mstorus.c");
				add_long (ex, "before", this_srf -> n_pair);
				add_long (ex, "after", n_pair);
				add_message (ex, "inconsistent number of neighbors");
				return;
			}
		}
	}

	this_srf -> n_pair = n_pair;
	sprintf (message, "%8ld neighbor pairs", n_pair);
	inform (message);
	return;
}
Ejemplo n.º 10
0
/* regular saddle surfaces for this torus */
void regular_saddle (struct surface *this_srf, struct torus *torus_ptr)
{
	int k, n_torus_arcs, arc_index;
	int index0, index1;
	struct arc *arc1, *arc2;
	struct circle *circle1, *circle2;
	double circle_points[MAX_SORT][3];
	double point_vector1[3];
	double point_vector2[3];
	short arc_orn[MAX_SORT];
	short indices[MAX_SORT];
	struct arc **arc_list, **arc_hdl;
	double wrap_angle;
    struct cept *ex;

	/* set up circles */

	circle1 = new_contact_circle (this_srf, torus_ptr, 0); if (error()) return;
	circle2 = new_contact_circle (this_srf, torus_ptr, 1); if (error()) return;

	/* count arcs belonging to torus */
	n_torus_arcs = 0;
	for (arc1 = torus_ptr -> first_arc; arc1 != NULL;
		arc1 = arc1 -> next) n_torus_arcs++;
	if (n_torus_arcs <= 0) return;

	/* must be even */
	if (0 != n_torus_arcs % 2) {
        ex = new_cept (GEOMETRY_ERROR, INCONSISTENCY, FATAL_SEVERITY);
        add_function (ex, "regular_saddle");
        add_source (ex, "msface.c");
        add_long (ex, "n_torus_arcs", n_torus_arcs);
        add_atom (ex, torus_ptr -> atm[0]);
        add_atom (ex, torus_ptr -> atm[1]);
		add_message (ex, "odd number of torus arcs");
		return;
	}
	if (n_torus_arcs > MAX_SORT) {
        ex = new_cept (GEOMETRY_ERROR, MSOVERFLOW, FATAL_SEVERITY);
        add_function (ex, "regular_saddle");
        add_source (ex, "msface.c");
        add_long (ex, "n_torus_arcs", n_torus_arcs);
        add_long (ex, "MAX_SORT", MAX_SORT);
        add_atom (ex, torus_ptr -> atm[0]);
        add_atom (ex, torus_ptr -> atm[1]);
		return;
	}

	/* allocate memory */
	arc_list = (struct arc **)
		allocate_pointers (ARC, n_torus_arcs);
	if (arc_list == NULL) {
        ex = new_cept (MEMORY_ERROR, ALLOCATION, FATAL_SEVERITY);
        add_function (ex, "regular_saddle");
        add_source (ex, "msface.c");
        add_atom (ex, torus_ptr -> atm[0]);
        add_atom (ex, torus_ptr -> atm[1]);
		return;
	}

	/* set up torus arc pointer list */
	for (arc1 = torus_ptr -> first_arc, arc_index = 0;
		arc_index < n_torus_arcs;
		arc1 = arc1 -> next, arc_index++) {
		arc_hdl = arc_list + arc_index;
		*arc_hdl = arc1;			/* pointer to arc */
	}

	setup_torus_arcs (torus_ptr -> axis, n_torus_arcs, arc_list,
		circle_points, arc_orn);
	if (error()) return;

	sort_points (torus_ptr -> center, torus_ptr -> radius,
		torus_ptr -> axis, n_torus_arcs, circle_points,
		arc_orn, indices);
	if (error()) return;

	for (arc_index = 0; arc_index < n_torus_arcs; arc_index += 2) {
		index0 = indices[arc_index];
		arc_hdl = arc_list + index0;
		arc1 = *arc_hdl;
		index1 = indices[arc_index+1];
		arc_hdl = arc_list + index1;
		arc2 = *arc_hdl;

		/* compute saddle wrap angle */
		for (k = 0; k < 3; k++) {
			point_vector1[k] =
				(circle_points[index0][k] - torus_ptr -> center[k]) /
					torus_ptr -> radius;
			point_vector2[k] =
				(circle_points[index1][k] - torus_ptr -> center[k]) /
					torus_ptr -> radius;
		}
		wrap_angle = positive_angle (point_vector1, point_vector2,
			torus_ptr -> axis);
		/* create saddle face */
		newsad (this_srf, arc1, arc2, circle1, circle2, torus_ptr, wrap_angle);
		if (error()) return;
	}

	/* free temporary memory */
	free_pointers (ARC, arc_list);
}
Ejemplo n.º 11
0
void cut_leaf (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct leaf *lf)
{
	int j, k, n, nx, nw, orn, sgn, i, used0, used1, nused;
	double t, xsmin, sangle, fsgn;
	double base[3], xpnts[2][3], vect[3];
	char message[MAXLINE];
	struct circle *cir;
	struct arc *al, *a;
	struct variety *vty;
	struct face *fac;
	struct leaf *lfcut;
	struct lax *xsptr, *xsend, *xsp;
	struct cycle *cyc;
	struct edge *edg;
	struct lax laxes[MAX_LAX];
    struct cept *ex;

	fac = lf -> fac;

	/* count number of edges for face */
	n = 2 * edges_in_face (fac);

	/* if toroidal, no cutting */

	if (fac -> shape == SADDLE || n <= 0) {
		/* clip and render leaf */
		clip_leaf (ms, current_surface, fine_pixel, lf);	
		return;
	}

	/* determine sign (plus for convex, minus for concave) */
	fsgn = ((lf -> shape == CONVEX) ? 1.0 : -1.0);

	/* create arc for leaf */
	al = leaf_to_arc (lf);
	vty = fac -> vty;
	cir = lf -> cir;
	for (k = 0; k < 3; k++)
		base[k] = lf -> ends[0][k] - cir -> center[k];
	normalize (base);

	/* determine intersection points between leaf and arcs of face */
	xsptr = &(laxes[0]);
	for (cyc = fac -> first_cycle; cyc != NULL; cyc = cyc -> next)
		for (edg = cyc -> first_edge; edg != NULL; edg = edg -> next) {
			a = edg -> arcptr;
			orn = edg -> orn;
			sgn = 1 - 2 * orn;
			/* call arc-arc intersection function */
			nx = arc_arc (al, a, xpnts);
			if (nx <= 0) continue;	/* no intersections */
			/* fill data into list */
			for (i = 0; i < nx; i++) {
				if (xsptr - &(laxes[0]) >= n) {
					ex = new_cept (ARRAY_ERROR,  MSOVERFLOW,  FATAL_SEVERITY);
					add_function (ex, "cut_leaf");
					add_source (ex, "msrender.c");
                    add_long (ex, "maximum number of leaf-arc intersections", n);
					return;
				}
				for (k = 0; k < 3; k++) {
					xsptr -> co[k] = xpnts[i][k];
					vect[k] = fsgn * (xsptr -> co[k] - vty -> center[k]);
				}
				t = sgn * triple_product (al -> cir -> axis, a -> cir -> axis, vect);
				xsptr -> ent = (t < 0);
				xsptr -> used = 0;
				xsptr++;
			}
		}

	xsend = xsptr;		/* mark end of list of intersection points */
	nx = xsend - &(laxes[0]);	/* compute number of intersection points */

	/* intersection parity error checking */
	if ((lf -> where[0] == lf -> where[1]) == (nx % 2)) {
		/* parity check fails,
		   flag leaf to check accessibility of every pixel of leaf */
		ms -> n_bdy_parity++;
		lf -> cep = 1;
		clip_leaf (ms, current_surface, fine_pixel, lf);
		lf -> cep = 0;
		frearc (al);
		return;
	}
	/* kludge to work around undiscovered bug for quartet cusps */
	if (lf -> atmnum[3] != 0) {
		/* flag leaf to check accessibility of every pixel of leaf */
		lf -> cep = 1;
		clip_leaf (ms, current_surface, fine_pixel, lf);
		lf -> cep = 0;
		frearc (al);
		return;
	}


	/* check for no intersection points */
	if (nx == 0) {
		if (lf -> where[0] == INACCESSIBLE) {
			/* entire leaf inaccessible: nothing to render */
			/* free temporary memory */
			frearc (al);
			return;
		}
		/* entire leaf accessible: render entire leaf */
		clip_leaf (ms, current_surface, fine_pixel, lf);
		if (error()) return;
		/* free temporary memory */
		frearc (al);
		return;
	}

	/* calculate angles for transitions between accessible
		and inaccessible */
	for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) {
		for (k = 0; k < 3; k++)
			vect[k] = xsptr -> co[k] - cir -> center[k];
		normalize (vect);
		xsptr -> angle = positive_angle (base, vect, cir -> axis);
	}

	/* initialization */
	used0 = 0;
	used1 = 0;
	nused = 0;
	nw = 0;

	/* count number of accessible endpoints of originial leaf */
	for (j = 0; j < 2; j++)
		if (lf -> where[j]) nw++;

	/* create new leaves */

	while (nused < nx + nw) {
		/* get starting point */
		if (!used0 && lf -> where[0] == ACCESSIBLE) {
			/* start at original endpoint */
			used0 = 1;		/* first originial endpoint used */
			nused++;		/* increment number used */
			lfcut = duplicate_leaf (lf);	/* duplicate leaf */
			sangle = 0.0;			/* starting angle */
		}
		else {
			/* look for unused cut vertex */
			xsmin = 4 * PI;
			xsp = NULL;
			for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) {
				if (xsptr -> used) continue;
				if (xsptr -> angle < xsmin) {
					xsmin = xsptr -> angle;
					xsp = xsptr;
				}
			}

			if (xsp == NULL) {
				if (lf -> where[1] == INACCESSIBLE) break;
				ms -> n_missing_leaves++;
				return;
			}
			if (!xsp -> ent) {
				ms -> n_missing_leaves++;
				return;
			}
			xsp -> used = 1;		/* mark as used */
			nused++;			/* increment number used */
			sangle = xsp -> angle;		/* starting angle */
			lfcut = duplicate_leaf (lf);	/* duplicate leaf */
			for (k = 0; k < 3; k++)
				lfcut -> ends[0][k] = xsp -> co[k];
		}

		/* get ending point */

		/* initialization */
		xsmin = 4 * PI;
		xsp = NULL;

		for (xsptr = &(laxes[0]); xsptr < xsend; xsptr++) {
			if (xsptr -> used) continue;		/* already used */
			if (xsptr -> angle < sangle) continue;	/* end after start */
			if (xsptr -> angle < xsmin) {
				/* best so far, save */
				xsmin = xsptr -> angle;
				xsp = xsptr;
			}
		}

		if (xsp == NULL) {
			if (used1 || lf -> where[1] == INACCESSIBLE) {
				ms -> n_missing_leaves++;
				return;
			}
			/* use East */
			used1 = 1;		/* mark East original endpoint used */
			nused++;		/* increment number used */
			for (k = 0; k < 3; k++)
				lfcut -> ends[1][k] = lf -> ends[1][k];
		}
		else {	/* use cut point */
			for (k = 0; k < 3; k++)
				lfcut -> ends[1][k] = xsp -> co[k];
			xsp -> used = 1;		/* mark as used */
			nused++;				/* increment number used */
		}
		/* we have a cut leaf; clip and render leaf */
		clip_leaf (ms, current_surface, fine_pixel, lfcut);
		free_leaf (lfcut);				/* free temporary memory */
	}

	/* free temporary memory */
	frearc (al);
	return;
}
Ejemplo n.º 12
0
void render_polyhedron (struct msscene *ms, struct surface *phn, double fine_pixel, long interpolate)
{
	int j, k, check, comp, hue, f, atm;
	int orn0, orn1, orn2;
	long t;
	long n_back, n_clipped, n_rendered;
	int vclipped[3], vback;
	double tcen[3];
	double trad;
	double tvertices[3][3];
	double tnormals[4][3];
	double tvalues[3];
	char message[MAXLINE];
	struct phnedg *edg0, *edg1, *edg2;
	struct phntri *tri;
	struct phnvtx *vtx, *vtxs[3];
    struct cept *ex;

	n_back = 0;
	n_clipped = 0;
	n_rendered = 0;
	f = (phn -> function[0]);
	if (phn -> phntri_handles == NULL) return;
	for (t = 0; t < phn -> n_phntri; t++) {
		tri = num2phntri (phn, t+1);
		if (tri == NULL) {
			ex = new_cept (POINTER_ERROR,  NULL_POINTER,  FATAL_SEVERITY);
			add_object (ex, PHNTRI, "tri");
			add_function (ex, "render_polyhedron");
			add_source (ex, "msrender.c");
			return;
		}
		for (k = 0; k < 3; k++)
			tcen[k] = tri -> center[k];
		trad = tri -> radius;
		edg0 = tri -> edg[0];
		edg1 = tri -> edg[1];
		edg2 = tri -> edg[2];
		orn0 = tri -> orn[0];
		orn1 = tri -> orn[1];
		orn2 = tri -> orn[2];
		vtxs[0] = edg0 -> pvt[orn0];
		vtxs[1] = edg1 -> pvt[orn1];
		vtxs[2] = edg2 -> pvt[orn2];
		for (k = 0; k < 3; k++)
			tnormals[3][k] = tri -> axis[k];
		for (j = 0; j < 3; j++) {
			vtx = vtxs[j];
			if      (f == 'x') tvalues[j] = vtx -> center[0];
			else if (f == 'y') tvalues[j] = vtx -> center[1];
			else if (f == 'z') tvalues[j] = vtx -> center[2];
			else if (f == 'u') tvalues[j] = vtx -> values[0];
			else if (f == 'v') tvalues[j] = vtx -> values[1];
			else if (f == 'w') tvalues[j] = vtx -> values[2];
			else tvalues[j] = vtx -> center[2]; /* default */
			for (k = 0; k < 3; k++) {
				tvertices[j][k] = vtx -> center[k];
				tnormals[j][k] = vtx -> outward[k];
			}
			/* check back-facing for triangle vertex normal */
			/* check clipping for triangle vertex */
			vclipped[j] =  ms -> clipping && phn -> clipping && clipped (ms, tvertices[j]);
		}
		vback =  (tnormals[3][2] < 0.0);
		if (ms -> clipping && phn -> clipping) {
			/* if all three vertices are clipped, triangle is clipped */
			check = (vclipped[0] || vclipped[1] || vclipped[2]);
			if (vclipped[0] && vclipped[1] && vclipped[2]) {
				n_clipped++;
				continue;
			}
		}
		else {
			check = 0;	/* no need to check triangle for being partially clipped */
			/* if back-facing, skip triangle */
			if (vback) {
				n_back++;
				continue;
			}
		}
		comp = tri -> comp;
		atm = tri -> atm;
		if (atm <= 0) {
			ex = new_cept (LOGIC_ERROR,  BOUNDS,  FATAL_SEVERITY);
			add_function (ex, "render_polyhedron");
			add_source (ex, "msrender.c");
			add_long (ex, "atm", (long) atm);
			add_message(ex, "invalid atom number for triangle");
			return;
		}
		hue = tri -> hue;
		render_triangle (ms, phn, fine_pixel, interpolate, 
			tcen, trad, tvertices, tnormals, tvalues, check, comp, hue, atm);
		if (error()) return;
		n_rendered++;
	}
	if (ms -> clipping && phn -> clipping)
		sprintf (message,"%8ld triangles rendered, %6ld clipped",
			n_rendered, n_clipped);
	else
		sprintf (message,"%8ld triangles rendered, %6ld back-facing",
			n_rendered, n_back);
	inform(message);
}
Ejemplo n.º 13
0
void slice_sphere (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct face *fac)
{
	int k, j;
	double yinc, y, rad, fsgn;
	double cir_center[3], cir_axis[3];
	char message[MAXLINE];
	struct leaf *lf;
	struct circle *cir;
	struct variety *vty;
    struct cept *ex;

	vty = fac -> vty;
	if (vty -> type != SPHERE) {
		ex = new_cept (ENUM_ERROR,  INVALID_VALUE,  FATAL_SEVERITY);
		add_function (ex, "slice_sphere");
		add_source (ex, "msrender.c");
        add_long (ex, "variety type", (long) vty -> type);
		return;
	}


	/* check versus window */
	for (k = 0; k < 3; k++) {
		if (vty -> center[k] + vty -> radii[0] < ms -> window[0][k]) return;
		if (vty -> center[k] - vty -> radii[0] > ms -> window[1][k]) return;
	}

	/* plus one for convex; minus one for concave */
	fsgn = ((fac -> shape == CONVEX) ? 1.0 : -1.0);


	/* set up circle for leaf */
	for (k = 0; k < 3; k++) {
		cir_center[k] = vty -> center[k];
		cir_axis[k] = ((k == 1) ? fsgn : 0.0);
	}
	cir = new_circle (cir_center, (double) 0.0, cir_axis);
	if (cir == NULL) {
		add_object (tail_cept, CIRCLE, "leaf circle");
		add_function (tail_cept, "slice_sphere");
		return;
	}
	lf = allocate_leaf ();
	if (lf == NULL) {
		add_object (tail_cept, LEAF, "leaf");
		add_function (tail_cept, "slice_sphere");
		return;
	}

	/* copy atom number from variety to leaf */
	for (j = 0; j < MAXPA; j++)
		lf -> atmnum[j] = fac -> vty -> atmnum[j];
	for (k = 0; k < 3; k++)
		lf -> focus[k] = vty -> center[k];

	/* set up leaf fields */
	lf -> cir = cir;
	lf -> shape = fac -> shape;
	lf -> type = fac -> vty -> type;
	lf -> fac = fac;
	lf -> side = OUTSIDE;
	lf -> comp = fac -> comp;
	lf -> input_hue = fac -> input_hue;

	/* y increment for lines of latitude on sphere */
	yinc = fine_pixel;

	/* one leaf per line of latitude */

	for (y = vty -> center[1] - vty -> radii[0] - yinc / 2;
		y < vty -> center[1] + vty -> radii[0]; y += yinc) {
		/* change circle center */
		cir -> center[1] = y;
		/* radius of circle of latitude */
		rad = (vty -> radii[0] * vty -> radii[0]) - (y - vty -> center[1])
			 * (y - vty -> center[1]);
		if (rad <= 0.0) continue;
		rad = sqrt (rad);
		if (rad <= 0.0) continue;
		cir -> radius = rad;
		/* leaf endpoints: west and east */
		for (j = 0; j < 2; j++)
			for (k = 0; k < 3; k++)
				lf -> ends[j][k] = cir -> center[k];
		lf -> ends[0][0] -= rad;
		lf -> ends[1][0] += rad;
		/* determine accessibility of endpoints of leaf */
		for (j = 0; j < 2; j++) {
			lf -> where[j] = point_in_face (lf -> ends[j], fac, 1);
			if (lf -> where[j] < 0) {
				ms -> n_bad_projection++;
				lf -> where[j] = 0;
			}
		}

		/* cut, clip and render (outer) leaf */
		lf -> cep = 0;
		lf -> clip_ep = 0;
		cut_leaf (ms, current_surface, fine_pixel, lf);
		if (error()) return;

		if (current_surface -> clipping) {
			/* cut, clip and render (inner) leaf */
			for (k = 0; k < 3; k++)
				cir -> axis[k] = ((k == 1) ? -fsgn : 0.0);
			lf -> cep = 0;
			lf -> clip_ep = 0;
			lf -> side = INSIDE;
			cut_leaf (ms, current_surface, fine_pixel, lf);
			if (error()) return;
			/* reset what we changed */
			lf -> side = OUTSIDE;
			for (k = 0; k < 3; k++)
				cir -> axis[k] = ((k == 1) ? fsgn : 0.0);
		}
	}
	free_leaf (lf);
	free_circle (cir);
	return;
}
Ejemplo n.º 14
0
void slice_elbow (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct face *fac)
{
	char message[MAXLINE];
	struct leaf *lf;
	struct circle *lfcir, *torcir;
	struct arc *torarc;
	struct vertex *torvtx[2];
	int i, j, k, nfocus, atmnum;
	double anginc, bigrad;
	double atmcen[3], ccens[2][3], cradii[2];
	double focus[3], vect[3], z_axis[3], base[3];
	struct variety *vty;
	double *foci;
    struct cept *ex;
	
	vty = fac -> vty;
	atmnum = vty -> atmnum[0];
	if (debug >= 2) {
		sprintf (message,"render elbow face for atom %5d", atmnum);
		inform(message);
	}
	for (k = 0; k < 3; k++)
		atmcen[k] = *(current_surface -> atom_centers + 3 * (atmnum - 1) + k);
	for (j = 0; j < 2; j++)
		cradii[j] = vty -> radii[1];
	for (j = 0; j < 2; j++)
		for (k = 0; k < 3; k++) {
			ccens[j][k] = vty -> ccens[j][k];
		}
	bigrad = distance (atmcen, ccens[0]) + cradii[0];
	for (k = 0; k < 3; k++) {
		if (atmcen[k] + bigrad < ms -> window[0][k]) return;
		if (atmcen[k] - bigrad > ms -> window[1][k]) return;
	}
	/* leaf circle */
	lfcir = allocate_circle ();
	if (lfcir == NULL) {
		ex = new_cept (MEMORY_ERROR,  ALLOCATION,  FATAL_SEVERITY);
		add_object (ex, CIRCLE, "leaf circle");
		add_function (ex, "slice_elbow");
		add_source (ex, "msrender.c");
		return;
	}
	/* leaf */
	lf = allocate_leaf ();
	if (lf == NULL) {
		add_object (tail_cept, LEAF, "leaf");
		add_function (tail_cept, "slice_sphere");
		return;
	}
	/* torus circle radius, center, axis */
	torcir = new_circle (vty -> center, vty -> radii[0], vty -> axis);
	if (torcir == NULL) {
		add_object (tail_cept, CIRCLE, "torus circle");
		add_function (tail_cept, "slice_elbow");
		return;
	}
	/* torus arc */
	torarc = allocate_arc ();
	if (torarc == NULL) {
		add_object (tail_cept, ARC, "torus arc");
		add_function (tail_cept, "slice_elbow");
		add_source (tail_cept, "msrender.c");
		return;
	}
	for (j = 0; j < 2; j++) {
		torvtx[j] = allocate_vertex ();
		if (error()) {
			add_object (tail_cept, VERTEX, "torus vertex");
			add_function (tail_cept, "slice_elbow");
			add_source (tail_cept, "msrender.c");
			return;
		}
	}
	/* set up leaf fields */
	for (k = 0; k < MAXPA; k++)
		lf -> atmnum[k] = vty -> atmnum[k];
	lf -> cir = lfcir;
	lf -> shape = CONVEX;		/* to avoid reversing normal vector */
	lf -> type = vty -> type;
	lf -> fac = fac;
	lf -> cep = 0;
	lf -> clip_ep = 0;
	lf -> side = OUTSIDE;
	lf -> comp = fac -> comp;
	lf -> input_hue = fac -> input_hue;
	for (j = 0; j < 2; j++)
		lf -> where[j] = ACCESSIBLE;

	/* setup torus central circle for subdivision */
	anginc = fine_pixel / ((vty -> radii[0] + cradii[0]));
	torcir -> radius = vty -> radii[0];
	for (k = 0; k < 3; k++) {
		torcir -> center[k] = vty -> center[k];
		torcir -> axis[k] = vty -> axis[k];
	}
	torarc -> cir = torcir;
	for (j = 0; j < 2; j++) {
		torarc -> vtx[j] = torvtx[j];
		for (k = 0; k < 3; k++)
			torvtx[j] -> center[k] = ccens[j][k];
	}
	foci = (double *) NULL;
	nfocus = render_sub_arc (torarc, &foci, anginc);
	if (nfocus < 2) {
		ex = new_cept (LOGIC_ERROR, MSUNDERFLOW, FATAL_SEVERITY);
        add_function (ex, "slice_elbow");
        add_source (ex, "msrender.c");
        add_long (ex, "number of foci", (long) nfocus);
		return;
	}

	/* create leaves */
	for (i = 0; i < nfocus; i++) {
		for (k = 0; k < 3; k++) {
			focus[k] = (*(foci + 3 * i + k));
			lfcir -> center[k] = focus[k];
			lf -> focus[k] = focus[k];
		}
		lfcir -> radius = cradii[0];
		/* compute tangent to torus central circle */
		for (k = 0; k < 3; k++)
			vect[k] = focus[k] - vty -> center[k];
		cross (vty -> axis, vect, lfcir -> axis);
		normalize (lfcir -> axis);
		for (k = 0; k < 3; k++)
			z_axis[k] = ((k == 2) ? 1.0 : 0.0);
		cross (lfcir -> axis, z_axis, base);
		if (norm (base) <= 0.0) {
			continue;
		}
		normalize (base);
		for (k = 0; k < 3; k++) {
			lf -> ends[0][k] = lfcir -> center[k] - lfcir -> radius * base[k];
			lf -> ends[1][k] = lfcir -> center[k] + lfcir -> radius * base[k];
		}
		/* clip and render leaf */
		clip_leaf (ms, current_surface, fine_pixel, lf);
		if (error()) return;
	}
	free_doubles (foci, 0, VERTS);
	free_leaf (lf);
	free_arc (torarc);
	free_circle (torcir);
	free_circle (lfcir);
	for (j = 0; j < 2; j++)
		free_vertex (torvtx[j]);
}
Ejemplo n.º 15
0
void slice_torus (struct msscene *ms, struct surface *current_surface, double fine_pixel, double probe_radius, struct face *fac)
{
	int k, j, i, nfocus, near1, naif;
	double anginc, bigrad;
	double focus[3], vect1[3], vect2[3], vect[3], qvect[3];
	double dtq, tcv[3];
	double *foci = (double *) NULL;
	char message[MAXLINE];
	struct leaf *lf;
	struct circle *cir1, *cir2, *cir3;
	struct circle *lfcir, *torcir;
	struct variety *vty, *atm1, *atm2;
	struct arc *a, *nxta;
	struct arc *torarc;
	struct vertex *torvtx[2];
	struct vertex *qvtx;
	struct vertex *conevtx;
	struct cycle *cyc;
	struct edge *edg;
    struct cept *ex;

	vty = fac -> vty;
	if (vty -> type != TORUS) {
		ex = new_cept (GEOMETRY_ERROR,  INCONSISTENCY,  FATAL_SEVERITY);
		add_function (ex, "slice_torus");
		add_source (ex, "msrender.c");
        add_long (ex, "variety type", (long) vty -> type);
		return;
	}
	if (vty -> tube) {
		slice_elbow (ms, current_surface, fine_pixel, fac);
		return;
	}

	if (debug >= 2) {
		sprintf (message,"render saddle face for atoms %5d %5d",
			vty -> atmnum[0], vty -> atmnum[1]);
		inform(message);
	}

	/* get pointers to atom varieties */
	atm1 = *(current_surface -> variety_handles + fac -> vty -> atmnum[0] - 1);
	atm2 = *(current_surface -> variety_handles + fac -> vty -> atmnum[1] - 1);

	/* check versus window */
	bigrad = distance (atm1 -> center, atm2 -> center) +
		atm1 -> radii[0] + atm2 -> radii[0];

	for (k = 0; k < 3; k++) {
		if (vty -> center[k] + bigrad < ms -> window[0][k]) return;
		if (vty -> center[k] - bigrad > ms -> window[1][k]) return;
	}
	/* leaf circle */
	lfcir = allocate_circle ();
	if (error()) {
		add_object (tail_cept, CIRCLE, "leaf circle");
		add_function (tail_cept, "slice_torus");
		return;
	}
	/* leaf */
	lf = allocate_leaf ();
	if (error()) {
		add_object (tail_cept, LEAF, "leaf");
		add_function (tail_cept, "slice_sphere");
		return;
	}
	/* torus circle radius, center, axis */
	torcir = new_circle (vty -> center, vty -> radii[0], vty -> axis);
	if (torcir == NULL) {
		add_object (tail_cept, CIRCLE, "torus circle");
		add_function (tail_cept, "slice_circle");
		return;
	}
	/* torus arc */
	torarc = allocate_arc ();
	if (error()) {
		add_object (tail_cept, ARC, "torus arc");
		add_function (tail_cept, "slice_torus");
		add_source (tail_cept, "msrender.c");
		return;
	}
	for (j = 0; j < 2; j++) {
		torvtx[j] = allocate_vertex ();
		if (error()) {
			add_object (tail_cept, VERTEX, "torus vertex");
			add_function (tail_cept, "slice_torus");
			add_source (tail_cept, "msrender.c");
			return;
		}
	}
	torarc -> cir = torcir;
	/* copy atom numbers from variety to leaf */
	for (k = 0; k < MAXPA; k++)
		lf -> atmnum[k] = fac -> vty -> atmnum[k];

	/* set up leaf fields */
	lf -> cir = lfcir;
	lf -> shape = fac -> shape;
	lf -> type = fac -> vty -> type;
	lf -> fac = fac;
	lf -> cep = 0;
	lf -> clip_ep = 0;
	lf -> side = OUTSIDE;
	lf -> comp = fac -> comp;
	lf -> input_hue = fac -> input_hue;

	/* both endpoints of saddle face leaf are always accessible */
	for (j = 0; j < 2; j++)
		lf -> where[j] = ACCESSIBLE;

	/* angular increment for rotation of leaf about torus axis */
	anginc = fine_pixel / (vty -> radii[0]);

	/* next we need endpoints for torus arc */
	/* get them from concave arcs bounding saddle face */

	/* intialization */
	cir1 = NULL;
	cir2 = NULL;
	cir3 = NULL;
	qvtx = NULL;
	conevtx = NULL;
	near1 = 0;

	/* look for concave arcs */
	naif = 0;
	for (cyc = fac -> first_cycle; cyc != NULL; cyc = cyc -> next)
		for (edg = cyc -> first_edge; edg != NULL; edg = edg -> next) {
			naif++;
			a = edg -> arcptr;
			if (a -> shape == CONVEX) {
				cir3 = a -> cir;
				continue;
			}
			if (edg -> next == NULL)
				nxta = cyc -> first_edge -> arcptr;
			else
				nxta = edg -> next -> arcptr;
			if (along (edg, vty -> axis))
				cir2 = a -> cir;
			else
				cir1 = a -> cir;
			/* check for cusp vertex */
			if (a -> shape == CONCAVE && nxta -> shape == CONCAVE) {
				/* cusp point joints two concave arcs */
				qvtx = a -> vtx[1-edg->orn];
			}
		}

	dtq = probe_radius * probe_radius - vty -> radii[0] * vty -> radii[0];

	/* later: note: check PI in bubbles */

	if (naif == 1) {
		if (dtq <= 0.0) {
			ex = new_cept (GEOMETRY_ERROR,  INCONSISTENCY,  FATAL_SEVERITY);
			add_function (ex, "slice_torus");
			add_source (ex, "msrender.c");
			add_message(ex, "toroidal face with only one arc, but not cone");
			return;
		}
		if (cir3 == NULL) {
			ex = new_cept (GEOMETRY_ERROR,  INCONSISTENCY,  FATAL_SEVERITY);
			add_function (ex, "slice_torus");
			add_source (ex, "msrender.c");
			add_message(ex, "toroidal face with only one arc, but no contact circle");
			return;
		}
		/* cone */
		qvtx = allocate_vertex ();
		if (error()) {
			add_object (tail_cept, VERTEX, "CUSP VERTEX");
			add_function (tail_cept, "slice_torus");
			add_source (tail_cept, "msrender.c");
			return;
		}
		conevtx = qvtx;
		dtq = sqrt (dtq);
		for (k = 0; k < 3; k++)
			tcv[k] = cir3 -> center[k] - torcir -> center[k];
		normalize (tcv);
		for (k = 0; k < 3; k++)
			qvtx -> center[k] = torcir -> center[k] + dtq * tcv[k];
		/* hope this is enough */
	}
	if (cir1 == NULL) informd2 ("cir1 null");
	if (cir2 == NULL) informd2 ("cir2 null");
	if (qvtx != NULL) informd2 ("cusp present");

	/* check for cusp vertex */
	if (qvtx != NULL) {
		for (k = 0; k < 3; k++)
			qvect[k] = qvtx -> center[k] - vty -> center[k];
		near1 = (dot_product (qvect, vty -> axis) < 0.0);
	}

	/* check for hoop saddle face */
	if (cir1 == NULL || cir2 == NULL) {
		for (j = 0; j < 2; j++)
			torarc -> vtx[j] = NULL;
		informd2 ("complete toroidal hoop");
	}
	else {
		/* concave arc circle centers are endpoints of sphere rolling */
		for (k = 0; k < 3; k++) {
			torvtx[0] -> center[k] = cir1 -> center[k];
			torvtx[1] -> center[k] = cir2 -> center[k];
		}
		for (j = 0; j < 2; j++)
			torarc -> vtx[j] = torvtx[j];
		sprintf (message, "saddle rendering (from): %8.3f %8.3f %8.3f",
			cir1 -> center[0], cir1 -> center[1], cir1 -> center[2]);
		informd2 (message);
		sprintf (message, "saddle rendering (to)  : %8.3f %8.3f %8.3f",
			cir2 -> center[0], cir2 -> center[1], cir2 -> center[2]);
		informd2 (message);
	}

	/* the probe sphere centers are the foci of the leaves */
	nfocus = render_sub_arc (torarc, &foci, anginc);
	if (nfocus < 2) {
		ex = new_cept (LOGIC_ERROR, MSUNDERFLOW, FATAL_SEVERITY);
        add_function (ex, "slice_torus");
        add_source (ex, "msrender.c");
        add_long (ex, "number of foci", (long) nfocus);
		return;
	}
	sprintf (message, "nfocus = %d", nfocus);
	informd2 (message);

	/* create leaves */
	for (i = 0; i < nfocus; i++) {
		for (k = 0; k < 3; k++) {
			focus[k] = (*(foci + 3 * i + k));
			lfcir -> center[k] = focus[k];
			lf -> focus[k] = focus[k];
		}

		/* unit vectors from focus toward atoms */
		for (k = 0; k < 3; k++) {
			vect1[k] = atm1 -> center[k] - focus[k];
			vect2[k] = atm2 -> center[k] - focus[k];
		}
		/* correct for cusp vertex */
		if (qvtx != NULL) {
			if (near1)
				for (k = 0; k < 3; k++)
					vect2[k] = qvtx -> center[k] - focus[k];
			else
				for (k = 0; k < 3; k++)
					vect1[k] = qvtx -> center[k] - focus[k];
		}
		/* normalize vectors to unit length */
		normalize (vect1);
		normalize (vect2);

		/* leaf circle radius is probe radius */
		lfcir -> radius = probe_radius;
		/* set up endpoints of leaf */
		for (k = 0; k < 3; k++) {
			lf -> ends[0][k] = focus[k] + lfcir -> radius * vect1[k];
			lf -> ends[1][k] = focus[k] + lfcir -> radius * vect2[k];
		}
		/* compute leaf circle axis */
		for (k = 0; k < 3; k++)
			vect[k] = focus[k] - vty -> center[k];
		cross (vty -> axis, vect, lfcir -> axis);
		normalize (lfcir -> axis);

		/* clip and render leaf */
		clip_leaf (ms, current_surface, fine_pixel, lf);
		if (error()) return;
	}

	/* return temporary memory */
	if (!free_doubles (foci, 0, VERTS)) {
		ex = new_cept (MEMORY_ERROR,  FREEING,  FATAL_SEVERITY);
		add_variable (ex, VERTS, "foci");
		add_function (ex, "slice_torus");
		add_source (ex, "msrender.c");
		return;
	}

	free_leaf (lf);
	free_arc (torarc);
	free_circle (torcir);
	free_circle (lfcir);
	for (j = 0; j < 2; j++)
		free_vertex (torvtx[j]);
	if (conevtx != NULL) free_vertex (conevtx);
	return;
}
Ejemplo n.º 16
0
    int
gui_mch_dialog(
    int		 type,
    char_u	*title,
    char_u	*message,
    char_u	*buttons,
    int		 dfltbutton,
    char_u	*textfield,
    int		ex_cmd)
{
    FARPROC	dp;
    LPWORD	p, pnumitems;
    int		numButtons;
    int		*buttonWidths, *buttonPositions;
    int		buttonYpos;
    int		nchar, i;
    DWORD	lStyle;
    int		dlgwidth = 0;
    int		dlgheight;
    int		editboxheight;
    int		horizWidth;
    int		msgheight;
    char_u	*pstart;
    char_u	*pend;
    char_u	*tbuffer;
    RECT	rect;
    HWND	hwnd;
    HDC		hdc;
    HFONT	oldFont;
    TEXTMETRIC	fontInfo;
    int		fontHeight;
    int		textWidth, minButtonWidth, messageWidth;
    int		maxDialogWidth;
    int		vertical;
    int		dlgPaddingX;
    int		dlgPaddingY;
    HGLOBAL	hglbDlgTemp;

#ifndef NO_CONSOLE
    /* Don't output anything in silent mode ("ex -s") */
    if (silent_mode)
	return dfltbutton;   /* return default option */
#endif

    /* If there is no window yet, open it. */
    if (s_hwnd == NULL && gui_mch_init() == FAIL)
	return dfltbutton;

    if ((type < 0) || (type > VIM_LAST_TYPE))
	type = 0;

    /* allocate some memory for dialog template */
    /* TODO should compute this really*/

    hglbDlgTemp = GlobalAlloc(GHND,  DLG_ALLOC_SIZE);
    if (hglbDlgTemp == NULL)
	return -1;

    p = (LPWORD) GlobalLock(hglbDlgTemp);

    if (p == NULL)
	return -1;

    /*
     * make a copy of 'buttons' to fiddle with it.  compiler grizzles because
     * vim_strsave() doesn't take a const arg (why not?), so cast away the
     * const.
     */
    tbuffer = vim_strsave(buttons);
    if (tbuffer == NULL)
	return -1;

    --dfltbutton;   /* Change from one-based to zero-based */

    /* Count buttons */
    numButtons = 1;
    for (i = 0; tbuffer[i] != '\0'; i++)
    {
	if (tbuffer[i] == DLG_BUTTON_SEP)
	    numButtons++;
    }
    if (dfltbutton >= numButtons)
	dfltbutton = 0;

    /* Allocate array to hold the width of each button */
    buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE);
    if (buttonWidths == NULL)
	return -1;

    /* Allocate array to hold the X position of each button */
    buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE);
    if (buttonPositions == NULL)
	return -1;

    /*
     * Calculate how big the dialog must be.
     */
    hwnd = GetDesktopWindow();
    hdc = GetWindowDC(hwnd);
    oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
    dlgPaddingX = DLG_OLD_STYLE_PADDING_X;
    dlgPaddingY = DLG_OLD_STYLE_PADDING_Y;

    GetTextMetrics(hdc, &fontInfo);
    fontHeight = fontInfo.tmHeight;

    /* Minimum width for horizontal button */
    minButtonWidth = GetTextWidth(hdc, "Cancel", 6);

    /* Maximum width of a dialog, if possible */
    GetWindowRect(s_hwnd, &rect);
    maxDialogWidth = rect.right - rect.left
		     - GetSystemMetrics(SM_CXFRAME) * 2;
    if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
	maxDialogWidth = DLG_MIN_MAX_WIDTH;

    /* Set dlgwidth to width of message */
    pstart = message;
    messageWidth = 0;
    msgheight = 0;
    do
    {
	pend = vim_strchr(pstart, DLG_BUTTON_SEP);
	if (pend == NULL)
	    pend = pstart + STRLEN(pstart);	/* Last line of message. */
	msgheight += fontHeight;
	textWidth = GetTextWidth(hdc, pstart, pend - pstart);
	if (textWidth > messageWidth)
	    messageWidth = textWidth;
	pstart = pend + 1;
    } while (*pend != NUL);
    dlgwidth = messageWidth;

    /* Add width of icon to dlgwidth, and some space */
    dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;

    if (msgheight < DLG_ICON_HEIGHT)
	msgheight = DLG_ICON_HEIGHT;

    /*
     * Check button names.  A long one will make the dialog wider.
     */
	 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
    if (!vertical)
    {
	// Place buttons horizontally if they fit.
	horizWidth = dlgPaddingX;
	pstart = tbuffer;
	i = 0;
	do
	{
	    pend = vim_strchr(pstart, DLG_BUTTON_SEP);
	    if (pend == NULL)
		pend = pstart + STRLEN(pstart);	// Last button name.
	    textWidth = GetTextWidth(hdc, pstart, pend - pstart);
	    if (textWidth < minButtonWidth)
		textWidth = minButtonWidth;
	    textWidth += dlgPaddingX;	    /* Padding within button */
	    buttonWidths[i] = textWidth;
	    buttonPositions[i++] = horizWidth;
	    horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */
	    pstart = pend + 1;
	} while (*pend != NUL);

	if (horizWidth > maxDialogWidth)
	    vertical = TRUE;	// Too wide to fit on the screen.
	else if (horizWidth > dlgwidth)
	    dlgwidth = horizWidth;
    }

    if (vertical)
    {
	// Stack buttons vertically.
	pstart = tbuffer;
	do
	{
	    pend = vim_strchr(pstart, DLG_BUTTON_SEP);
	    if (pend == NULL)
		pend = pstart + STRLEN(pstart);	// Last button name.
	    textWidth = GetTextWidth(hdc, pstart, pend - pstart);
	    textWidth += dlgPaddingX;		/* Padding within button */
	    textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */
	    if (textWidth > dlgwidth)
		dlgwidth = textWidth;
	    pstart = pend + 1;
	} while (*pend != NUL);
    }

    if (dlgwidth < DLG_MIN_WIDTH)
	dlgwidth = DLG_MIN_WIDTH;	/* Don't allow a really thin dialog!*/

    /* start to fill in the dlgtemplate information.  addressing by WORDs */
    lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ;

    add_long(lStyle);
    pnumitems = p;	/*save where the number of items must be stored*/
    add_byte(0);	// NumberOfItems(will change later)
    add_word(10);	// x
    add_word(10);	// y
    add_word(PixelToDialogX(dlgwidth));

    // Dialog height.
    if (vertical)
	dlgheight = msgheight + 2 * dlgPaddingY +
			      DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons;
    else
	dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight;

    // Dialog needs to be taller if contains an edit box.
    editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y;
    if (textfield != NULL)
	dlgheight += editboxheight;

    add_word(PixelToDialogY(dlgheight));

    add_byte(0);	//menu
    add_byte(0);	//class

    /* copy the title of the dialog */
    add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM));

    buttonYpos = msgheight + 2 * dlgPaddingY;

    if (textfield != NULL)
	buttonYpos += editboxheight;

    pstart = tbuffer; //dflt_text
    horizWidth = (dlgwidth - horizWidth) / 2;	/* Now it's X offset */
    for (i = 0; i < numButtons; i++)
    {
	/* get end of this button. */
	for (	pend = pstart;
		*pend && (*pend != DLG_BUTTON_SEP);
		pend++)
	    ;

	if (*pend)
	    *pend = '\0';

	/*
	 * NOTE:
	 * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets
	 * the focus to the first tab-able button and in so doing makes that
	 * the default!! Grrr.  Workaround: Make the default button the only
	 * one with WS_TABSTOP style. Means user can't tab between buttons, but
	 * he/she can use arrow keys.
	 *
	 * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the
	 * first one, so I changed the correct button to be this style. This
	 * is necessary because when an edit box is added, we need a button to
	 * be default.  The edit box will be the default control, and when the
	 * user presses enter from the edit box we want the default button to
	 * be pressed.
	 */
	if (vertical)
	{
	    p = add_dialog_element(p,
		    ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
			    ?  BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
		    PixelToDialogX(DLG_VERT_PADDING_X),
		    PixelToDialogY(buttonYpos /* TBK */
				   + 2 * fontHeight * i),
		    PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X),
		    (WORD)(PixelToDialogY(2 * fontHeight) - 1),
		    (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
	}
	else
	{
	    p = add_dialog_element(p,
		    ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
			     ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
		    PixelToDialogX(horizWidth + buttonPositions[i]),
		    PixelToDialogY(buttonYpos), /* TBK */
		    PixelToDialogX(buttonWidths[i]),
		    (WORD)(PixelToDialogY(2 * fontHeight) - 1),
		    (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
	}

	pstart = pend + 1;	/*next button*/

    }
    *pnumitems += numButtons;

    /* Vim icon */
    p = add_dialog_element(p, SS_ICON,
	    PixelToDialogX(dlgPaddingX),
	    PixelToDialogY(dlgPaddingY),
	    PixelToDialogX(DLG_ICON_WIDTH),
	    PixelToDialogY(DLG_ICON_HEIGHT),
	    DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82,
	    &dlg_icons[type]);


    /* Dialog message */
    p = add_dialog_element(p, SS_LEFT,
	    PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
	    PixelToDialogY(dlgPaddingY),
	    (WORD)(PixelToDialogX(messageWidth) + 1),
	    PixelToDialogY(msgheight),
	    DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message);

    /* Edit box */
    if (textfield != NULL)
    {
	p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER,
		PixelToDialogX(2 * dlgPaddingX),
		PixelToDialogY(2 * dlgPaddingY + msgheight),
		PixelToDialogX(dlgwidth - 4 * dlgPaddingX),
		PixelToDialogY(fontHeight + dlgPaddingY),
		DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield);
	*pnumitems += 1;
    }

    *pnumitems += 2;

    SelectFont(hdc, oldFont);
    ReleaseDC(hwnd, hdc);
    dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst);


    /* Let the dialog_callback() function know which button to make default
     * If we have an edit box, make that the default. We also need to tell
     * dialog_callback() if this dialog contains an edit box or not. We do
     * this by setting s_textfield if it does.
     */
    if (textfield != NULL)
    {
	dialog_default_button = DLG_NONBUTTON_CONTROL + 2;
	s_textfield = textfield;
    }
    else
    {
	dialog_default_button = IDCANCEL + 1 + dfltbutton;
	s_textfield = NULL;
    }

    /*show the dialog box modally and get a return value*/
    nchar = DialogBoxIndirect(
	    s_hinst,
	    (HGLOBAL) hglbDlgTemp,
	    s_hwnd,
	    (DLGPROC)dp);

    FreeProcInstance( dp );
    GlobalUnlock(hglbDlgTemp);
    GlobalFree(hglbDlgTemp);
    vim_free(tbuffer);
    vim_free(buttonWidths);
    vim_free(buttonPositions);


    return nchar;
}