text: /*
   * FIG : Facility for Interactive Generation of figures
   * Copyright (c) 1985-1988 by Supoj Sutanthavibul
   * Parts Copyright (c) 1989-2007 by Brian V. Smith
   * Parts Copyright (c) 1991 by Paul King
   *
   * Any party obtaining a copy of these files is granted, free of charge, a
   * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
   * nonexclusive right and license to deal in this software and documentation
   * files (the "Software"), including without limitation the rights to use,
   * copy, modify, merge, publish distribute, sublicense and/or sell copies of
   * the Software, and to permit persons who receive copies from any such
   * party to do so, with the only requirement being that the above copyright
   * and this permission notice remain intact.
   *
   */
  
  #include "fig.h"
  #include "resources.h"
  #include "mode.h"
  #include "object.h"
  #include "paintop.h"
  #include "d_text.h"
  #include "e_rotate.h"
  #include "e_scale.h"
  #include "u_create.h"
  #include "u_draw.h"
  #include "u_elastic.h"
  #include "u_search.h"
  #include "u_undo.h"
  #include "w_canvas.h"
  #include "w_drawprim.h"
  #include "w_mousefun.h"
  #include "w_msgpanel.h"
  #include "w_setup.h"
  
  #include "e_movept.h"
  #include "f_util.h"
  #include "u_bound.h"
  #include "u_fonts.h"
  #include "u_geom.h"
  #include "u_list.h"
  #include "u_markers.h"
  #include "u_redraw.h"
  #include "w_cursor.h"
  
  static Boolean	init_boxscale_ellipse(int x, int y);
  static Boolean	init_boxscale_line(int x, int y);
  static Boolean	init_boxscale_compound(int x, int y);
  static Boolean	init_scale_arc(void);
  static Boolean	init_scale_ellipse(void);
  static Boolean	init_scale_line(void);
  static Boolean	init_scale_spline(void);
  
  static void	scale_line(F_line *l, float sx, float sy, int refx, int refy);
  static void	scale_spline(F_spline *s, float sx, float sy, int refx, int refy);
  static void	scale_arc(F_arc *a, float sx, float sy, int refx, int refy);
  static void	scale_ellipse(F_ellipse *e, float sx, float sy, int refx, int refy);
  static void	scale_text(F_text *t, float sx, float sy, int refx, int refy);
  static void	scale_arrows(F_line *obj, float sx, float sy);
  static void	scale_arrow(F_arrow *arrow, float sx, float sy);
  
  static void	init_box_scale(F_line *obj, int type, int x, int y, int px, int py);
  static void	boxrelocate_ellipsepoint(F_ellipse *ellipse, int x, int y);
  static void	init_center_scale(F_line *obj, int type, int x, int y, int px, int py);
  static void	init_scale_compound(void);
  static void	rescale_points(F_line *obj, int x, int y);
  static void	relocate_ellipsepoint(F_ellipse *ellipse, int x, int y);
  static void	relocate_arcpoint(F_arc *arc, int x, int y);
  
  static void	fix_scale_arc(int x, int y);
  static void	fix_scale_spline(int x, int y);
  static void	fix_scale_line(int x, int y);
  static void	fix_scale_ellipse(int x, int y);
  static void	fix_boxscale_ellipse(int x, int y);
  static void	fix_boxscale_line(int x, int y);
  static void	fix_scale_compound(int x, int y);
  static void	fix_boxscale_compound(int x, int y);
  
  static void	cancel_scale_arc(void);
  static void	cancel_scale_spline(void);
  static void	cancel_scale_line(void);
  static void	cancel_scale_ellipse(void);
  static void	cancel_boxscale_ellipse(void);
  static void	cancel_boxscale_line(void);
  static void	cancel_scale_compound(void);
  static void	cancel_boxscale_compound(void);
  static void	prescale_compound(F_compound *c, int x, int y);
  
  
  
  void
  scale_selected(void)
  {
      set_mousefun("scale box", "scale about center", "",
  			LOC_OBJ, LOC_OBJ, LOC_OBJ);
      canvas_kbd_proc = null_proc;
      canvas_locmove_proc = null_proc;
      canvas_ref_proc = null_proc;
      init_searchproc_left(init_box_scale);
      init_searchproc_middle(init_center_scale);
      canvas_leftbut_proc = object_search_left;
      canvas_middlebut_proc = object_search_middle;
      canvas_rightbut_proc = null_proc;
      set_cursor(pick15_cursor);
      reset_action_on();
  }
  
  char *BOX_SCL_MSG = "Can't use box scale on selected object";
  char *BOX_SCL2_MSG = "Can't use box scale on selected object; try putting it into a compound";
  
  static void
  init_box_scale(F_line *obj, int type, int x, int y, int px, int py)
  {
      switch (type) {
      case O_POLYLINE:
  	cur_l = (F_line *) obj;
  	if (!init_boxscale_line(px, py))	/* non-box line */
  	    return;
  	break;
      case O_ELLIPSE:
  	cur_e = (F_ellipse *) obj;
  	if (!init_boxscale_ellipse(px, py))	/* selected center, ignore */
  	    return;
  	break;
      case O_COMPOUND:
  	cur_c = (F_compound *) obj;
  	if (!init_boxscale_compound(px, py))	/* non-box compound */
  	    return;
  	break;
      default:
  	put_msg(BOX_SCL2_MSG);
  	beep();
  	return;
      }
      set_mousefun("new posn", "", "cancel", LOC_OBJ, LOC_OBJ, LOC_OBJ);
      draw_mousefun_canvas();
      canvas_middlebut_proc = null_proc;
  }
  
  static void
  init_center_scale(F_line *obj, int type, int x, int y, int px, int py)
  {
      double	    dx, dy, l;
  
      cur_x = from_x = px;
      cur_y = from_y = py;
      constrained = BOX_SCALE;
      switch (type) {
      case O_POLYLINE:
  	cur_l = (F_line *) obj;
  	if (!init_scale_line())		/* selected center */
  	    return;
  	break;
      case O_SPLINE:
  	cur_s = (F_spline *) obj;
  	if (!init_scale_spline())	/* selected center */
  	    return;
  	break;
      case O_ELLIPSE:
  	cur_e = (F_ellipse *) obj;
  	if (!init_scale_ellipse())	/* selected center */
  	    return;
  	break;
      case O_ARC:
  	cur_a = (F_arc *) obj;
  	if (!init_scale_arc())		/* selected center */
  	    return;
  	break;
      case O_COMPOUND:
  	cur_c = (F_compound *) obj;
  	init_scale_compound();
  	break;
      }
  
      dx = (double) (from_x - fix_x);
      dy = (double) (from_y - fix_y);
      l = sqrt(dx * dx + dy * dy);
      cosa = fabs(dx / l);
      sina = fabs(dy / l);
  
      set_mousefun("", "new posn", "cancel", LOC_OBJ, LOC_OBJ, LOC_OBJ);
      draw_mousefun_canvas();
      canvas_leftbut_proc = null_proc;
  }
  
  static void
  wrapup_scale(void)
  {
      reset_action_on();
      scale_selected();
      draw_mousefun_canvas();
  }
  
  /*************************  ellipse  *******************************/
  
  static Boolean
  init_boxscale_ellipse(int x, int y)
  {
      double	    dx, dy, l;
  
      if (cur_e->type == T_ELLIPSE_BY_RAD ||
  	cur_e->type == T_CIRCLE_BY_RAD) {
  	if (x == cur_e->start.x && y == cur_e->start.y) {
  	    put_msg("Center point selected, ignored");
  	    return False;
  	} else {
  	    fix_x = cur_e->center.x - (x - cur_e->center.x);
  	    fix_y = cur_e->center.y - (y - cur_e->center.y);
  	}
      } else {
  	if (x == cur_e->start.x && y == cur_e->start.y) {
  	    fix_x = cur_e->end.x;
  	    fix_y = cur_e->end.y;
  	} else {
  	    fix_x = cur_e->start.x;
  	    fix_y = cur_e->start.y;
  	}
      }
      cur_x = from_x = x;
      cur_y = from_y = y;
      cur_angle = cur_e->angle;
  
      if (cur_x == fix_x || cur_y == fix_y) {
  	put_msg(BOX_SCL2_MSG);
  	beep();
  	return False;
      }
      set_action_on();
      toggle_ellipsemarker(cur_e);
      constrained = BOX_SCALE;
      dx = (double) (cur_x - fix_x);
      dy = (double) (cur_y - fix_y);
      l = sqrt(dx * dx + dy * dy);
      cosa = fabs(dx / l);
      sina = fabs(dy / l);
  
      set_cursor(crosshair_cursor);
      if ((cur_e->type == T_CIRCLE_BY_DIA) ||
  	(cur_e->type == T_CIRCLE_BY_RAD)) {
  	canvas_locmove_proc = constrained_resizing_cbd;
  	canvas_ref_proc = elastic_cbd;
  	elastic_cbd();
      } else {
  	canvas_locmove_proc = constrained_resizing_ebd;
  	canvas_ref_proc = elastic_ebd;
  	elastic_ebd();
      }
      canvas_leftbut_proc = fix_boxscale_ellipse;
      canvas_rightbut_proc = cancel_boxscale_ellipse;
      return True;
  }
  
  static void
  cancel_boxscale_ellipse(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      if ((cur_e->type == T_CIRCLE_BY_DIA) ||
  	(cur_e->type == T_CIRCLE_BY_RAD))
  	elastic_cbd();
      else
  	elastic_ebd();
      toggle_ellipsemarker(cur_e);
      wrapup_scale();
  }
  
  static void
  fix_boxscale_ellipse(int x, int y)
  {
      float	    dx, dy;
  
      if ((cur_e->type == T_CIRCLE_BY_DIA) ||
  	(cur_e->type == T_CIRCLE_BY_RAD))
  	elastic_cbd();
      else
  	elastic_ebd();
      adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
      new_e = copy_ellipse(cur_e);
      boxrelocate_ellipsepoint(new_e, cur_x, cur_y);
      /* find how much the radii changed */
      dx = 1.0 * new_e->radiuses.x / cur_e->radiuses.x;
      dy = 1.0 * new_e->radiuses.y / cur_e->radiuses.y;
      change_ellipse(cur_e, new_e);
      wrapup_scale();
      /* redraw anything under the old ellipse */
      redisplay_ellipse(cur_e);
      /* and the new one */
      redisplay_ellipse(new_e);
  }
  
  static void
  boxrelocate_ellipsepoint(F_ellipse *ellipse, int x, int y)
  {
      double	    dx, dy;
  
      set_temp_cursor(wait_cursor);
      draw_ellipse(ellipse, ERASE);
      if ((ellipse->type == T_CIRCLE_BY_RAD) ||
  	(ellipse->type == T_ELLIPSE_BY_RAD)) {
  	ellipse->end.x = x;
  	ellipse->end.y = y;
      } else {
  	if (ellipse->start.x == fix_x)
  	    ellipse->end.x = x;
  	if (ellipse->start.y == fix_y)
  	    ellipse->end.y = y;
  	if (ellipse->end.x == fix_x)
  	    ellipse->start.x = x;
  	if (ellipse->end.y == fix_y)
  	    ellipse->start.y = y;
      }
      if ((ellipse->type == T_CIRCLE_BY_DIA) ||
  	(ellipse->type == T_CIRCLE_BY_RAD)) {
  	dx = ellipse->center.x = round((fix_x + x) / 2);
  	dy = ellipse->center.y = round((fix_y + y) / 2);
  	dx -= x;
  	dy -= y;
  	ellipse->radiuses.x = round(sqrt(dx * dx + dy * dy));
  	ellipse->radiuses.y = ellipse->radiuses.x;
      } else {
  	ellipse->center.x = (fix_x + x) / 2;
  	ellipse->center.y = (fix_y + y) / 2;
  	ellipse->radiuses.x = abs(ellipse->center.x - fix_x);
  	ellipse->radiuses.y = abs(ellipse->center.y - fix_y);
      }
      if ((ellipse->type == T_CIRCLE_BY_RAD) ||
  	(ellipse->type == T_ELLIPSE_BY_RAD)) {
  	ellipse->start.x = ellipse->center.x;
  	ellipse->start.y = ellipse->center.y;
      }
      reset_cursor();
  }
  
  static Boolean
  init_scale_ellipse(void)
  {
      fix_x = cur_e->center.x;
      fix_y = cur_e->center.y;
      cur_angle = cur_e->angle;
      if (from_x == fix_x && from_y == fix_y) {
  	put_msg("Center point selected, ignored");
  	return False;
      }
      set_action_on();
      toggle_ellipsemarker(cur_e);
      set_cursor(crosshair_cursor);
      canvas_locmove_proc = scaling_ellipse;
      canvas_ref_proc = elastic_scale_curellipse;
      elastic_scaleellipse(cur_e);
      canvas_middlebut_proc = fix_scale_ellipse;
      canvas_rightbut_proc = cancel_scale_ellipse;
      if (cur_e->type == T_ELLIPSE_BY_RAD)
  	length_msg(MSG_RADIUS2);
      else if (cur_e->type == T_CIRCLE_BY_RAD)
  	length_msg(MSG_RADIUS);
      else
  	length_msg(MSG_DIAM);
      return True;		/* all is Ok */
  }
  
  static void
  cancel_scale_ellipse(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_scaleellipse(cur_e);
      toggle_ellipsemarker(cur_e);
      wrapup_scale();
  }
  
  static void
  fix_scale_ellipse(int x, int y)
  {
      elastic_scaleellipse(cur_e);
      adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
      new_e = copy_ellipse(cur_e);
      relocate_ellipsepoint(new_e, cur_x, cur_y);
      change_ellipse(cur_e, new_e);
      wrapup_scale();
      /* redraw anything under the old ellipse */
      redisplay_ellipse(cur_e);
      /* and the new one */
      redisplay_ellipse(new_e);
  }
  
  static void
  relocate_ellipsepoint(F_ellipse *ellipse, int x, int y)
  {
      double	    newx, newy, oldx, oldy;
      double	    newd, oldd, scalefact;
  
      set_temp_cursor(wait_cursor);
      draw_ellipse(ellipse, ERASE);
  
      newx = x - fix_x;
      newy = y - fix_y;
      newd = sqrt(newx * newx + newy * newy);
      oldx = from_x - fix_x;
      oldy = from_y - fix_y;
      oldd = sqrt(oldx * oldx + oldy * oldy);
      scalefact = newd / oldd;
  
      ellipse->radiuses.x = round(ellipse->radiuses.x * scalefact);
      ellipse->radiuses.y = round(ellipse->radiuses.y * scalefact);
      ellipse->end.x = fix_x + round((ellipse->end.x - fix_x) * scalefact);
      ellipse->end.y = fix_y + round((ellipse->end.y - fix_y) * scalefact);
      ellipse->start.x = fix_x + round((ellipse->start.x - fix_x) * scalefact);
      ellipse->start.y = fix_y + round((ellipse->start.y - fix_y) * scalefact);
      reset_cursor();
  }
  
  /***************************  arc  *********************************/
  
  static Boolean
  init_scale_arc(void)
  {
      fix_x = cur_a->center.x;
      fix_y = cur_a->center.y;
      if (from_x == fix_x && from_y == fix_y) {
  	put_msg("Center point selected, ignored");
  	return False;
      }
      set_action_on();
      toggle_arcmarker(cur_a);
      elastic_scalearc(cur_a);
      set_cursor(crosshair_cursor);
      canvas_locmove_proc = scaling_arc;
      canvas_ref_proc = elastic_scale_curarc;
      canvas_middlebut_proc = fix_scale_arc;
      canvas_rightbut_proc = cancel_scale_arc;
      return True;
  }
  
  static void
  cancel_scale_arc(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_scalearc(cur_a);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      toggle_arcmarker(cur_a);
      wrapup_scale();
  }
  
  static void
  fix_scale_arc(int x, int y)
  {
      double	    newx, newy, oldx, oldy;
      double	    newd, oldd, scalefact;
  
      elastic_scalearc(cur_a);
  
      adjust_box_pos(x, y, from_x, from_y, &x, &y);
      new_a = copy_arc(cur_a);
  
      newx = cur_x - fix_x;
      newy = cur_y - fix_y;
      newd = sqrt(newx * newx + newy * newy);
      oldx = from_x - fix_x;
      oldy = from_y - fix_y;
      oldd = sqrt(oldx * oldx + oldy * oldy);
      scalefact = newd / oldd;
      /* scale any arrowheads */
      scale_arrows((F_line *)new_a,scalefact,scalefact);
  
      relocate_arcpoint(new_a, x, y);
      change_arc(cur_a, new_a);
      wrapup_scale();
      /* redraw anything under the old arc */
      redisplay_arc(cur_a);
      /* and the new one */
      redisplay_arc(new_a);
  }
  
  static void
  relocate_arcpoint(F_arc *arc, int x, int y)
  {
      double	    newx, newy, oldx, oldy;
      double	    newd, oldd, scalefact;
      float	    xx, yy;
      F_pos	    p0, p1, p2;
  
      newx = x - fix_x;
      newy = y - fix_y;
      newd = sqrt(newx * newx + newy * newy);
  
      oldx = from_x - fix_x;
      oldy = from_y - fix_y;
      oldd = sqrt(oldx * oldx + oldy * oldy);
  
      scalefact = newd / oldd;
  
      p0 = arc->point[0];
      p1 = arc->point[1];
      p2 = arc->point[2];
      p0.x = fix_x + round((p0.x - fix_x) * scalefact);
      p0.y = fix_y + round((p0.y - fix_y) * scalefact);
      p1.x = fix_x + round((p1.x - fix_x) * scalefact);
      p1.y = fix_y + round((p1.y - fix_y) * scalefact);
      p2.x = fix_x + round((p2.x - fix_x) * scalefact);
      p2.y = fix_y + round((p2.y - fix_y) * scalefact);
      if (compute_arccenter(p0, p1, p2, &xx, &yy)) {
  	arc->point[0].x = p0.x;
  	arc->point[0].y = p0.y;
  	arc->point[1].x = p1.x;
  	arc->point[1].y = p1.y;
  	arc->point[2].x = p2.x;
  	arc->point[2].y = p2.y;
  	arc->center.x = xx;
  	arc->center.y = yy;
  	arc->direction = compute_direction(p0, p1, p2);
      }
      set_modifiedflag();
  }
  
  /**************************  spline  *******************************/
  
  static Boolean
  init_scale_spline(void)
  {
      int		    sumx, sumy, cnt;
      F_point	   *p;
  
      p = cur_s->points;
      if (closed_spline(cur_s))
  	p = p->next;
      for (sumx = 0, sumy = 0, cnt = 0; p != NULL; p = p->next) {
  	sumx = sumx + p->x;
  	sumy = sumy + p->y;
  	cnt++;
      }
      fix_x = sumx / cnt;
      fix_y = sumy / cnt;
      if (from_x == fix_x && from_y == fix_y) {
  	put_msg("Center point selected, ignored");
  	return False;
      }
      set_action_on();
      set_cursor(crosshair_cursor);
      toggle_splinemarker(cur_s);
      elastic_scalepts(cur_s->points);
      canvas_locmove_proc = scaling_spline;
      canvas_ref_proc = elastic_scale_curspline;
      canvas_middlebut_proc = fix_scale_spline;
      canvas_rightbut_proc = cancel_scale_spline;
      return True;
  }
  
  static void
  cancel_scale_spline(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_scalepts(cur_s->points);
      toggle_splinemarker(cur_s);
      wrapup_scale();
  }
  
  static void
  fix_scale_spline(int x, int y)
  {
      elastic_scalepts(cur_s->points);
      canvas_ref_proc = null_proc;
      adjust_box_pos(x, y, from_x, from_y, &x, &y);
      /* make a copy of the original and save as unchanged object */
      old_s = copy_spline(cur_s);
      clean_up();
      set_latestspline(old_s);
      set_action_object(F_EDIT, O_SPLINE);
      old_s->next = cur_s;
      /* now change the original to become the new object */
      rescale_points((F_line *)cur_s, x, y);
      wrapup_scale();
      /* redraw anything under the old spline */
      redisplay_spline(old_s);
      /* and the new one */
      redisplay_spline(cur_s);
  }
  
  /***************************  compound	********************************/
  
  static Boolean
  init_boxscale_compound(int x, int y)
  {
      int		    xmin, ymin, xmax, ymax;
      double	    dx, dy, l;
  
      xmin = min2(cur_c->secorner.x, cur_c->nwcorner.x);
      ymin = min2(cur_c->secorner.y, cur_c->nwcorner.y);
      xmax = max2(cur_c->secorner.x, cur_c->nwcorner.x);
      ymax = max2(cur_c->secorner.y, cur_c->nwcorner.y);
  
      if (xmin == xmax || ymin == ymax) {
  	put_msg(BOX_SCL_MSG);
  	beep();
  	return False;
      }
      set_action_on();
      toggle_compoundmarker(cur_c);
      set_cursor(crosshair_cursor);
  
      if (x == xmin) {
  	fix_x = xmax;
  	from_x = x;
  	if (y == ymin) {
  	    fix_y = ymax;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else if (y == ymax) {
  	    fix_y = ymin;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else {
  	    fix_y = ymax;
  	    from_y = ymin;
  	    constrained = BOX_HSTRETCH;
  	}
      } else if (x == xmax) {
  	fix_x = xmin;
  	from_x = x;
  	if (y == ymin) {
  	    fix_y = ymax;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else if (y == ymax) {
  	    fix_y = ymin;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else {
  	    fix_y = ymax;
  	    from_y = ymin;
  	    constrained = BOX_HSTRETCH;
  	}
      } else {
  	if (y == ymin) {
  	    fix_y = ymax;
  	    from_y = y;
  	    fix_x = xmax;
  	    from_x = xmin;
  	    constrained = BOX_VSTRETCH;
  	} else {		/* y == ymax */
  	    fix_y = ymin;
  	    from_y = y;
  	    fix_x = xmax;
  	    from_x = xmin;
  	    constrained = BOX_VSTRETCH;
  	}
      }
  
      cur_x = from_x;
      cur_y = from_y;
  
      if (constrained == BOX_SCALE) {
  	dx = (double) (cur_x - fix_x);
  	dy = (double) (cur_y - fix_y);
  	l = sqrt(dx * dx + dy * dy);
  	cosa = fabs(dx / l);
  	sina = fabs(dy / l);
      }
      boxsize_scale_msg(1);
      elastic_box(fix_x, fix_y, cur_x, cur_y);
      canvas_locmove_proc = constrained_resizing_scale_box;
      canvas_ref_proc = elastic_fixedbox;
      canvas_leftbut_proc = fix_boxscale_compound;
      canvas_rightbut_proc = cancel_boxscale_compound;
      return True;
  }
  
  static void
  cancel_boxscale_compound(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_box(fix_x, fix_y, cur_x, cur_y);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      toggle_compoundmarker(cur_c);
      wrapup_scale();
  }
  
  static void
  fix_boxscale_compound(int x, int y)
  {
      double	    scalex, scaley;
  
      elastic_box(fix_x, fix_y, cur_x, cur_y);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      adjust_box_pos(x, y, from_x, from_y, &x, &y);
      new_c = copy_compound(cur_c);
      scalex = (double) (x - fix_x) / (from_x - fix_x);
      scaley = (double) (y - fix_y) / (from_y - fix_y);
      scale_compound(new_c, scalex, scaley, fix_x, fix_y);
      change_compound(cur_c, new_c);
      wrapup_scale();
      /* redraw anything under the old compound */
      redisplay_compound(cur_c);
      /* and the new one */
      redisplay_compound(new_c);
  }
  
  static void
  init_scale_compound(void)
  {
      fix_x = (cur_c->nwcorner.x + cur_c->secorner.x) / 2;
      fix_y = (cur_c->nwcorner.y + cur_c->secorner.y) / 2;
      set_action_on();
      toggle_compoundmarker(cur_c);
      set_cursor(crosshair_cursor);
      elastic_scalecompound(cur_c);
      canvas_locmove_proc = scaling_compound;
      canvas_ref_proc = elastic_scale_curcompound;
      canvas_middlebut_proc = fix_scale_compound;
      canvas_rightbut_proc = cancel_scale_compound;
  }
  
  static void
  cancel_scale_compound(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_scalecompound(cur_c);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      toggle_compoundmarker(cur_c);
      wrapup_scale();
  }
  
  static void
  fix_scale_compound(int x, int y)
  {
      elastic_scalecompound(cur_c);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
      /* make a copy of the original and save as unchanged object */
      old_c = copy_compound(cur_c);
      clean_up();
      set_latestcompound(old_c);
      set_action_object(F_EDIT, O_COMPOUND);
      old_c->next = cur_c;
      /* now change the original to become the new object */
      prescale_compound(cur_c, cur_x, cur_y);
      wrapup_scale();
      /* redraw anything under the old compound */
      redisplay_compound(old_c);
      /* and the new one */
      redisplay_compound(cur_c);
  }
  
  static void
  prescale_compound(F_compound *c, int x, int y)
  {
      double	    newx, newy, oldx, oldy;
      double	    newd, oldd, scalefact;
  
      newx = x - fix_x;
      newy = y - fix_y;
      newd = sqrt(newx * newx + newy * newy);
      oldx = from_x - fix_x;
      oldy = from_y - fix_y;
      oldd = sqrt(oldx * oldx + oldy * oldy);
      scalefact = newd / oldd;
      scale_compound(c, scalefact, scalefact, fix_x, fix_y);
  }
  
  void
  scale_compound(F_compound *c, double sx, double sy, int refx, int refy)
  {
      F_line	   *l;
      F_spline	   *s;
      F_ellipse	   *e;
      F_text	   *t;
      F_arc	   *a;
      F_compound	   *c1;
      int		    x1, y1, x2, y2;
  
      /* if sx and sy == 1.0, return now */
      if (sx == 0.0 && sy == 0.0)
  	return;
  
      /* check if really a dimension line */
      if (rescale_dimension_line(c, sx, sy, refx, refy))
  	return; /* yes, return now */
  
      x1 = round(refx + (c->nwcorner.x - refx) * sx);
      y1 = round(refy + (c->nwcorner.y - refy) * sy);
      x2 = round(refx + (c->secorner.x - refx) * sx);
      y2 = round(refy + (c->secorner.y - refy) * sy);
      c->nwcorner.x = min2(x1, x2);
      c->nwcorner.y = min2(y1, y2);
      c->secorner.x = max2(x1, x2);
      c->secorner.y = max2(y1, y2);
  
      for (l = c->lines; l != NULL; l = l->next) {
  	scale_line(l, sx, sy, refx, refy);
      }
      for (s = c->splines; s != NULL; s = s->next) {
  	scale_spline(s, sx, sy, refx, refy);
      }
      for (a = c->arcs; a != NULL; a = a->next) {
  	scale_arc(a, sx, sy, refx, refy);
      }
      for (e = c->ellipses; e != NULL; e = e->next) {
  	scale_ellipse(e, sx, sy, refx, refy);
      }
      for (t = c->texts; t != NULL; t = t->next) {
  	scale_text(t, sx, sy, refx, refy);
      }
      for (c1 = c->compounds; c1 != NULL; c1 = c1->next) {
  	scale_compound(c1, sx, sy, refx, refy);
  	/* if there's a dimension line in this compound reset corners */
  	c->nwcorner.x = min2(c->nwcorner.x, c1->nwcorner.x);
  	c->nwcorner.y = min2(c->nwcorner.y, c1->nwcorner.y);
  	c->secorner.x = max2(c->secorner.x, c1->secorner.x);
  	c->secorner.y = max2(c->secorner.y, c1->secorner.y);
      }
  }
  
  Boolean
  rescale_dimension_line(F_compound *dimline, float scalex, float scaley, int refx, int refy)
  {
      F_line	   *line, *box, *tick1, *tick2;
      F_text	   *text;
      double	    length, dx, dy, angle;
      float	    save_rotnangle, save_rotn_dirn;
      int		    p1x, p1y, p2x, p2y, centerx, centery;
      int		    x1, x2, y1, y2, save;
      int		    theight, tlen2, tht2;
      PR_SIZE	    tsize;
      char	    str[80], comment[100];
      F_point	   *pnt;
      Boolean	    fixed_text;
      int		    save_lthick, save_t1thick, save_t2thick;
  
      /* locate the line components of the dimension line */
      if (!dimline_components(dimline, &line, &tick1, &tick2, &box))
  	/* not a dimension line, return */
  	return False;
  
      /* see if user has deleted main line */
      if (!line)
  	return False;
  
      /* get the two endpoints and scale them */
      p1x = round(refx + (line->points->x - refx) * scalex);
      p1y = round(refy + (line->points->y - refy) * scaley);
      p2x = round(refx + (line->points->next->x - refx) * scalex);
      p2y = round(refy + (line->points->next->y - refy) * scaley);
  
      /* put them back */
      line->points->x = p1x;
      line->points->y = p1y;
      line->points->next->x = p2x;
      line->points->next->y = p2y;
  
      /* if drawn right to left or top to bottom at 90 degrees swap the two points */
      if (p1x > p2x || (p1y < p2y && p1x == p2x)) {
  	save = p1x; p1x = p2x; p2x = save;
  	save = p1y; p1y = p2y; p2y = save;
      }
      dx = p2x-p1x;
      dy = p2y-p1y;
  
      /* get the text component */
      text = dimline->texts;
      if (!text) {
  	/* hmm, user must have deleted it */
  	text = create_text();
  	if (box)
  	    text->depth  = box->depth-1;
  	else
  	    text->depth  = line->depth-2;
  	add_depth(O_TXT, text->depth);
  	text->cstring = (char *) NULL;	/* the string will be put in later */
  	text->color = cur_dimline_textcolor;
  	text->font = cur_dimline_font;
  	text->size = cur_dimline_fontsize;
  	text->flags = cur_dimline_psflag? PSFONT_TEXT: 0;
  	text->pen_style = -1;
  	text->type = T_CENTER_JUSTIFIED;
  	dimline->texts = text;
      }
      fixed_text = text && text->comments && (strncasecmp(text->comments,"fixed text", 10)==0);
      if (!fixed_text) {
  	/* length of the line */
  	length = sqrt(dx*dx + dy*dy);
  
  	/* make text with the length */
  	make_dimension_string(length, str, False);
  
  	/* put the new length in the comment */
  	sprintf(comment, "Dimension line: %s",str);
  	/* free any old comment */
  	if (dimline->comments)
  	    free(dimline->comments);
  	/* put in the new one */
  	dimline->comments = strdup(comment);
      }
  
      /* center the box for the length string */
      centerx = (p1x+p2x)/2;
      centery = (p1y+p2y)/2;
      /* angle of the line */
      angle = -atan2(dy, dx);
  
      /* recompute the text, text angle and text box */
      /* new string, but only if comment doesn't say "fixed text" */
      if (!fixed_text) {
  	 /* free any old string */
  	 if (text->cstring)
  	    free(text->cstring);
  	 text->cstring = strdup(str);
      }
      /* recalculate text sizes */
      text->fontstruct = lookfont(x_fontnum(text->flags, text->font), text->size);
      text->zoom = 1.0;
      tsize = textsize(text->fontstruct, strlen(text->cstring), text->cstring);
      text->ascent  = tsize.ascent;
      text->descent = tsize.descent;
      text->length  = tsize.length;
      theight = tsize.ascent + tsize.descent;
      text->angle = angle;
      text->base_x = centerx + sin(angle)*round(theight/2.0 - tsize.descent);
      text->base_y = centery + cos(angle)*round(theight/2.0 - tsize.descent);
  
      /* half the text length + a margin */
      tlen2 = text->length/2 + 60;
      /* half the height + a margin */
      tht2 = theight/2 + 60;
  
      /* save global rotation angle and direction to use our own */
      save_rotnangle = act_rotnangle;
      save_rotn_dirn = rotn_dirn;
      act_rotnangle = -angle * 180.0 / M_PI;
      rotn_dirn = 1;
  
      /* now rescale the text box (the box) */
      if (box) {
  	pnt = box->points;
  	pnt->x = centerx-tlen2;
  	pnt->y = centery-tht2;
  	pnt = pnt->next;
  	pnt->x = centerx-tlen2;
  	pnt->y = centery+tht2;
  	pnt = pnt->next;
  	pnt->x = centerx+tlen2;
  	pnt->y = centery+tht2;
  	pnt = pnt->next;
  	pnt->x = centerx+tlen2;
  	pnt->y = centery-tht2;
  	pnt = pnt->next;
  	pnt->x = centerx-tlen2;
  	pnt->y = centery-tht2;
  
  	/* rotate the box around the center */
  	rotate_line(box, centerx, centery);
      } /* if (box) */
  
      /* now recalculate the end ticks */
      if (tick1) {
  	pnt = tick1->points;
  	pnt->x = p1x;
  	pnt->y = p1y-tht2;
  	pnt = pnt->next;
  	pnt->x = p1x;
  	pnt->y = p1y+tht2;
  	/* rotate the line around the endpoint */
  	rotate_line(tick1, p1x, p1y);
      }
  
      /* the other tick */
      if (tick2) {
  	pnt = tick2->points;
  	pnt->x = p2x;
  	pnt->y = p2y-tht2;
  	pnt = pnt->next;
  	pnt->x = p2x;
  	pnt->y = p2y+tht2;
  	/* rotate the line around the endpoint */
  	rotate_line(tick2, p2x, p2y);
      }
  
      /* restore original rotation angle and direction */
      act_rotnangle = save_rotnangle;
      rotn_dirn = save_rotn_dirn;
  
      /* get the bounds of the compound */
      /* but set the thicknesses of the line and ticks to 0 so they aren't taken into account */
      save_lthick = line->thickness;
      line->thickness = 0;
      if (tick1) {
  	save_t1thick = tick1->thickness;
  	tick1->thickness = 0;
      }
      if (tick2) {
  	save_t2thick = tick2->thickness;
  	tick2->thickness = 0;
      }
  
      compound_bound(dimline, &x1, &y1, &x2, &y2);
      /* restore the thicknesses */
      line->thickness = save_lthick;
      if (tick1)
  	tick1->thickness = save_t1thick;
      if (tick2)
  	tick2->thickness = save_t2thick;
  
      dimline->nwcorner.x = x1;
      dimline->nwcorner.y = y1;
      dimline->secorner.x = x2;
      dimline->secorner.y = y2;
  
      return True;
  }
  
  static void
  scale_line(F_line *l, float sx, float sy, int refx, int refy)
  {
      F_point	   *p;
  
      for (p = l->points; p != NULL; p = p->next) {
  	p->x = round(refx + (p->x - refx) * sx);
  	p->y = round(refy + (p->y - refy) * sy);
      }
      /* now scale the radius for an arc-box */
      if (l->type == T_ARCBOX) {
  	int h,w;
  	/* scale by the average of height/width factor */
  	l->radius = round(l->radius * (sx+sy)/2);
  	/* if the radius is larger than half the width or height, set it to the
  	   minimum of the width or heigth divided by 2 */
  	w = abs(l->points->x-l->points->next->next->x);
  	h = abs(l->points->y-l->points->next->next->y);
  	if ((l->radius > w/2) || (l->radius > h/2))
  		l->radius = min2(w,h)/2;
  	/* finally, if it is 0, make it 1 */
  	if (l->radius == 0)
  		l->radius = 1;
      }
      /* finally, scale any arrowheads */
      scale_arrows(l,sx,sy);
  }
  
  static void
  scale_spline(F_spline *s, float sx, float sy, int refx, int refy)
  {
      F_point	   *p;
  
      for (p = s->points; p != NULL; p = p->next) {
  	p->x = round(refx + (p->x - refx) * sx);
  	p->y = round(refy + (p->y - refy) * sy);
      }
      /* scale any arrowheads */
      scale_arrows((F_line *)s,sx,sy);
  }
  
  static void
  scale_arc(F_arc *a, float sx, float sy, int refx, int refy)
  {
      int		    i;
      F_point	    p[3];
  
      for (i = 0; i < 3; i++) {
  	/* save original points for co-linear check later */
  	p[i].x = a->point[i].x;
  	p[i].y = a->point[i].y;
  	a->point[i].x = round(refx + (a->point[i].x - refx) * sx);
  	a->point[i].y = round(refy + (a->point[i].y - refy) * sy);
      }
      if (compute_arccenter(a->point[0], a->point[1], a->point[2],
  		          &a->center.x, &a->center.y) == 0) {
  	/* the new arc is co-linear, move the middle point one pixel */
  	if (a->point[0].x == a->point[1].x) { /* vertical, move middle left or right */
  	    if (p[1].x > p[0].x)
  		a->point[1].x++;	/* convex to the right -> ) */
  	    else
  		a->point[1].x--;	/* convex to the left -> ( */
  	}
  	/* check ALSO for horizontally co-linear in case all three points are equal */
  	if (a->point[0].y == a->point[1].y) { /* horizontal, move middle point up or down */
  	    if (p[1].y > p[0].y)
  		a->point[1].y++;	/* curves up */
  	    else
  		a->point[1].y--;	/* curves down */
  	}
  	/* now check if the endpoints are equal, move one of them */
  	if (a->point[0].x == a->point[2].x &&
  	    a->point[0].y == a->point[2].y)
  		a->point[2].x++;
  	/* make up a center */
  	a->center.x = a->point[1].x;
  	a->center.y = a->point[1].y;
      }
      a->direction = compute_direction(a->point[0], a->point[1], a->point[2]);
      /* scale any arrowheads */
      scale_arrows((F_line *)a,sx,sy);
  }
  
  static void
  scale_ellipse(F_ellipse *e, float sx, float sy, int refx, int refy)
  {
      e->center.x = round(refx + (e->center.x - refx) * sx);
      e->center.y = round(refy + (e->center.y - refy) * sy);
      e->start.x = round(refx + (e->start.x - refx) * sx);
      e->start.y = round(refy + (e->start.y - refy) * sy);
      e->end.x = round(refx + (e->end.x - refx) * sx);
      e->end.y = round(refy + (e->end.y - refy) * sy);
      e->radiuses.x = abs(round(e->radiuses.x * sx));
      e->radiuses.y = abs(round(e->radiuses.y * sy));
      /* if this WAS a circle and is NOW an ellipse, change type to reflect */
      if (e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA) {
  	if (e->radiuses.x != e->radiuses.y)
  	    e->type -= 2;
      }
      /* conversely, if this WAS an ellipse and is NOW a circle, change type */
      else if (e->type == T_ELLIPSE_BY_RAD || e->type == T_ELLIPSE_BY_DIA) {
  	if (e->radiuses.x == e->radiuses.y)
  	    e->type += 2;
      }
  }
  
  static void
  scale_text(F_text *t, float sx, float sy, int refx, int refy)
  {
      int newsize;
      t->base_x = round(refx + (t->base_x - refx) * sx);
      t->base_y = round(refy + (t->base_y - refy) * sy);
      if (!rigid_text(t)) {
          newsize = round(t->size * sx);
  	if (newsize < MIN_FONT_SIZE)
  	    sx = (float) MIN_FONT_SIZE / t->size;
  	else if (MAX_FONT_SIZE < newsize)
  	    sx = (float) MAX_FONT_SIZE / t->size;
  	t->size = round(t->size * sx);
  	t->ascent = round(t->ascent * sx);
  	t->descent = round(t->descent * sx);
  	t->length = round(t->length * sx);
      }
      /* rescale font */
      reload_text_fstruct(t);
  }
  
  
  /***************************  line  ********************************/
  
  static Boolean
  init_boxscale_line(int x, int y)
  {
      int		    xmin, ymin, xmax, ymax;
      F_point	   *p0, *p1, *p2;
      double	    dx, dy, l;
  
      if (cur_l->type != T_BOX &&
  	cur_l->type != T_ARCBOX &&
  	cur_l->type != T_PICTURE) {
  	put_msg(BOX_SCL2_MSG);
  	beep();
  	return False;
      }
      p0 = cur_l->points;
      p1 = p0->next;
      p2 = p1->next;
      xmin = min3(p0->x, p1->x, p2->x);
      ymin = min3(p0->y, p1->y, p2->y);
      xmax = max3(p0->x, p1->x, p2->x);
      ymax = max3(p0->y, p1->y, p2->y);
  
      if (xmin == xmax || ymin == ymax) {
  	put_msg(BOX_SCL_MSG);
  	beep();
  	return False;
      }
      set_action_on();
      toggle_linemarker(cur_l);
  
      if (x == xmin) {
  	fix_x = xmax;
  	from_x = x;
  	if (y == ymin) {
  	    fix_y = ymax;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else if (y == ymax) {
  	    fix_y = ymin;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else {
  	    fix_y = ymax;
  	    from_y = ymin;
  	    constrained = BOX_HSTRETCH;
  	}
      } else if (x == xmax) {
  	fix_x = xmin;
  	from_x = x;
  	if (y == ymin) {
  	    fix_y = ymax;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else if (y == ymax) {
  	    fix_y = ymin;
  	    from_y = y;
  	    constrained = BOX_SCALE;
  	} else {
  	    fix_y = ymax;
  	    from_y = ymin;
  	    constrained = BOX_HSTRETCH;
  	}
      } else {
  	if (y == ymin) {
  	    fix_y = ymax;
  	    from_y = y;
  	    fix_x = xmax;
  	    from_x = xmin;
  	    constrained = BOX_VSTRETCH;
  	} else {		/* y == ymax */
  	    fix_y = ymin;
  	    from_y = y;
  	    fix_x = xmax;
  	    from_x = xmin;
  	    constrained = BOX_VSTRETCH;
  	}
      }
  
      cur_x = from_x;
      cur_y = from_y;
      set_cursor(crosshair_cursor);
  
      if (constrained == BOX_SCALE) {
  	dx = (double) (cur_x - fix_x);
  	dy = (double) (cur_y - fix_y);
  	l = sqrt(dx * dx + dy * dy);
  	cosa = fabs(dx / l);
  	sina = fabs(dy / l);
      }
      boxsize_msg(1);
      elastic_box(fix_x, fix_y, cur_x, cur_y);
      canvas_locmove_proc = constrained_resizing_box;
      canvas_ref_proc = elastic_fixedbox;
      canvas_leftbut_proc = fix_boxscale_line;
      canvas_rightbut_proc = cancel_boxscale_line;
      return True;
  }
  
  static void
  cancel_boxscale_line(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_box(fix_x, fix_y, cur_x, cur_y);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      toggle_linemarker(cur_l);
      wrapup_scale();
  }
  
  static void
  fix_boxscale_line(int x, int y)
  {
      int		owd,oht, nwd, nht;
      float	scalex, scaley;
  
      elastic_box(fix_x, fix_y, cur_x, cur_y);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      adjust_box_pos(x, y, from_x, from_y, &x, &y);
      new_l = copy_line(cur_l);
      draw_line(cur_l, ERASE);
      assign_newboxpoint(new_l, fix_x, fix_y, x, y);
      owd = abs(cur_l->points->x - cur_l->points->next->next->x);
      oht = abs(cur_l->points->y - cur_l->points->next->next->y);
      nwd = abs(new_l->points->x - new_l->points->next->next->x);
      nht = abs(new_l->points->y - new_l->points->next->next->y);
      if (new_l->type == T_PICTURE) {
  	if (signof(fix_x - from_x) != signof(fix_x - x))
  	    new_l->pic->flipped = 1 - new_l->pic->flipped;
  	if (signof(fix_y - from_y) != signof(fix_y - y))
  	    new_l->pic->flipped = 1 - new_l->pic->flipped;
      } else if (new_l->type == T_ARCBOX) {	/* scale the radius also */
  	scale_radius(cur_l, new_l, owd, oht, nwd, nht);
      }
      change_line(cur_l, new_l);
      scalex = 1.0 * nwd/owd;
      scaley = 1.0 * nht/oht;
      wrapup_scale();
      /* redraw anything under the old line */
      redisplay_line(cur_l);
      /* and the new one */
      redisplay_line(new_l);
  }
  
  void
  scale_radius(F_line *old, F_line *new, int owd, int oht, int nwd, int nht)
  {
  	float wdscale, htscale;
  
  	wdscale = 1.0 * nwd/owd;
  	htscale = 1.0 * nht/oht;
  	/* scale by the average of height/width factor */
  	new->radius = round(new->radius * (wdscale+htscale)/2);
  	/* next, if the radius is larger than half the width, set it to the
  	   minimum of the width or heigth divided by 2 */
  	if ((new->radius > nwd/2) || (new->radius > nht/2))
  		new->radius = min2(nwd,nht)/2;
  	/* finally, if it is 0, make it 1 */
  	if (new->radius == 0)
  		new->radius = 1;
  }
  
  static Boolean
  init_scale_line(void)
  {
      int		    sumx, sumy, cnt;
      F_point	   *p;
  
      p = cur_l->points;
      if (cur_l->type != T_POLYLINE)
  	p = p->next;
      for (sumx = 0, sumy = 0, cnt = 0; p != NULL; p = p->next) {
  	sumx = sumx + p->x;
  	sumy = sumy + p->y;
  	cnt++;
      }
      fix_x = sumx / cnt;
      fix_y = sumy / cnt;
      if (from_x == fix_x && from_y == fix_y) {
  	put_msg("Center point selected, ignored");
  	return False;
      }
      set_action_on();
      toggle_linemarker(cur_l);
      set_cursor(crosshair_cursor);
      if (cur_l->type == T_BOX || cur_l->type == T_ARCBOX || cur_l->type == T_PICTURE) {
  	boxsize_msg(2);	/* factor of 2 because measurement is from midpoint */
      }
      elastic_scalepts(cur_l->points);
      canvas_locmove_proc = scaling_line;
      canvas_ref_proc = elastic_scale_curline;
      canvas_middlebut_proc = fix_scale_line;
      canvas_rightbut_proc = cancel_scale_line;
      return True;
  }
  
  static void
  cancel_scale_line(void)
  {
      canvas_ref_proc = canvas_locmove_proc = null_proc;
      elastic_scalepts(cur_l->points);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      toggle_linemarker(cur_l);
      wrapup_scale();
  }
  
  static void
  fix_scale_line(int x, int y)
  {
      int		owd,oht, nwd, nht;
  
      elastic_scalepts(cur_l->points);
      /* erase last lengths if appres.showlengths is true */
      erase_lengths();
      adjust_box_pos(x, y, from_x, from_y, &x, &y);
      /* make a copy of the original and save as unchanged object */
      old_l = copy_line(cur_l);
      clean_up();
      set_latestline(old_l);
      set_action_object(F_EDIT, O_POLYLINE);
      old_l->next = cur_l;
      /* now change the original to become the new object */
      rescale_points(cur_l, x, y);
      /* and scale the radius if ARCBOX */
      if (cur_l->type == T_ARCBOX) {
  	owd = abs(old_l->points->x - old_l->points->next->next->x);
  	oht = abs(old_l->points->y - old_l->points->next->next->y);
  	nwd = abs(cur_l->points->x - cur_l->points->next->next->x);
  	nht = abs(cur_l->points->y - cur_l->points->next->next->y);
  	scale_radius(cur_l, cur_l, owd, oht, nwd, nht);
      }
      wrapup_scale();
      /* redraw anything under the old line */
      redisplay_line(old_l);
      /* and the new one */
      redisplay_line(cur_l);
  }
  
  static void
  rescale_points(F_line *obj, int x, int y)
  {
      F_point	   *p;
      double	    newx, newy, oldx, oldy;
      double	    newd, oldd, scalefact;
  
      newx = x - fix_x;
      newy = y - fix_y;
      newd = sqrt(newx * newx + newy * newy);
  
      oldx = from_x - fix_x;
      oldy = from_y - fix_y;
      oldd = sqrt(oldx * oldx + oldy * oldy);
  
      scalefact = newd / oldd;
      for (p = obj->points; p != NULL; p = p->next) {
  	p->x = fix_x + (p->x - fix_x) * scalefact;
  	p->y = fix_y + (p->y - fix_y) * scalefact;
      }
      /* scale any arrows */
      scale_arrows(obj,scalefact,scalefact);
      set_modifiedflag();
  }
  
  /* scale arrowheads on passed object by sx,sy */
  
  static void
  scale_arrows(F_line *obj, float sx, float sy)
  {
      scale_arrow(obj->for_arrow,sx,sy);
      scale_arrow(obj->back_arrow,sx,sy);
  }
  
  /* scale arrowhead by sx,sy - for now just use average
     of sx,sy for scale factor */
  
  static void
  scale_arrow(F_arrow *arrow, float sx, float sy)
  {
      if (arrow == 0)
  	return;
  
      /* scale the thickness by the average of the horizontal and vertical scale factors */
      sx = ((float)fabs(sx)+(float)fabs(sy))/2.0;
      arrow->ht *= sx;
      arrow->wd *= sx;
      return;
  }
  