home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xfig / part18 < prev    next >
Encoding:
Text File  |  1993-05-26  |  69.3 KB  |  2,380 lines

  1. Newsgroups: comp.sources.x
  2. From: envbvs@epb9.lbl.gov (Brian V. Smith)
  3. Subject: v19i130:  xfig - Draw amd manipulate objects in an X-Window, Part18/27
  4. Message-ID: <1993May21.021636.6948@sparky.imd.sterling.com>
  5. X-Md4-Signature: f7210be6a947313ca4081b682bf074c7
  6. Sender: chris@sparky.imd.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Fri, 21 May 1993 02:16:36 GMT
  9. Approved: chris@sparky.imd.sterling.com
  10.  
  11. Submitted-by: envbvs@epb9.lbl.gov (Brian V. Smith)
  12. Posting-number: Volume 19, Issue 130
  13. Archive-name: xfig/part18
  14. Environment: X11
  15. Supersedes: xfig: Volume 16, Issue 6-30,39
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 18 (of 27)."
  24. # Contents:  u_draw.c w_rulers.c
  25. # Wrapped by envbvs@epb9.lbl.gov.lbl.gov on Mon May  3 12:06:02 1993
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'u_draw.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'u_draw.c'\"
  29. else
  30. echo shar: Extracting \"'u_draw.c'\" \(34170 characters\)
  31. sed "s/^X//" >'u_draw.c' <<'END_OF_FILE'
  32. X/*
  33. X * FIG : Facility for Interactive Generation of figures
  34. X * Copyright (c) 1985 by Supoj Sutanthavibul
  35. X * Copyright (c) 1990 by Brian V. Smith
  36. X * Copyright (c) 1992 by James Tough
  37. X *
  38. X * "Permission to use, copy, modify, distribute, and sell this software and its
  39. X * documentation for any purpose is hereby granted without fee, provided that
  40. X * the above copyright notice appear in all copies and that both the copyright
  41. X * notice and this permission notice appear in supporting documentation. 
  42. X * No representations are made about the suitability of this software for 
  43. X * any purpose.  It is provided "as is" without express or implied warranty."
  44. X */
  45. X
  46. X#include "fig.h"
  47. X#include "resources.h"
  48. X#include "object.h"
  49. X#include "paintop.h"
  50. X#include "u_bound.h"
  51. X#include "u_create.h"
  52. X#include "u_draw.h"
  53. X#include "w_canvas.h"
  54. X#include "w_drawprim.h"
  55. X#include "w_zoom.h"
  56. X
  57. Xtypedef unsigned char byte;
  58. Xextern PIX_ROT_FONT lookfont();
  59. X
  60. X/************** POLYGON/CURVE DRAWING FACILITIES ****************/
  61. X
  62. Xstatic int    npoints;
  63. Xstatic int    max_points;
  64. Xstatic XPoint  *points;
  65. Xstatic int    allocstep;
  66. X
  67. Xstatic        Boolean
  68. Xinit_point_array(init_size, step_size)
  69. X    int            init_size, step_size;
  70. X{
  71. X    npoints = 0;
  72. X    max_points = init_size;
  73. X    allocstep = step_size;
  74. X    if (max_points > MAXNUMPTS) {
  75. X    put_msg("Too many points, recompile with MAXNUMPTS > %d in w_drawprim.h",
  76. X        MAXNUMPTS);
  77. X    max_points = MAXNUMPTS;
  78. X    }
  79. X    if ((points = (XPoint *) malloc(max_points * sizeof(XPoint))) == 0) {
  80. X    fprintf(stderr, "xfig: insufficient memory to allocate point array\n");
  81. X    return False;
  82. X    }
  83. X    return True;
  84. X}
  85. X
  86. Xstatic        Boolean
  87. Xadd_point(x, y)
  88. X    int            x, y;
  89. X{
  90. X    if (npoints >= max_points) {
  91. X    XPoint           *tmp_p;
  92. X
  93. X    max_points += allocstep;
  94. X    if (max_points >= MAXNUMPTS)
  95. X        return False;    /* stop; it is not closing */
  96. X
  97. X    if ((tmp_p = (XPoint *) realloc(points,
  98. X                    max_points * sizeof(XPoint))) == 0) {
  99. X        fprintf(stderr,
  100. X            "xfig: insufficient memory to reallocate point array\n");
  101. X        return False;
  102. X    }
  103. X    points = tmp_p;
  104. X    }
  105. X    points[npoints].x = (short) x;
  106. X    points[npoints].y = (short) y;
  107. X    npoints++;
  108. X    return True;
  109. X}
  110. X
  111. Xstatic void
  112. Xdraw_point_array(w, op, line_width, line_style, style_val, fill_style, color)
  113. X    Window        w;
  114. X    int            op;
  115. X    int            line_width, line_style;
  116. X    float        style_val;
  117. X    int            fill_style;
  118. X    Color        color;
  119. X{
  120. X    pw_lines(w, points, npoints, op,
  121. X         line_width, line_style, style_val, fill_style, color);
  122. X    free(points);
  123. X}
  124. X
  125. X/*********************** ARC ***************************/
  126. X
  127. Xdraw_arc(a, op)
  128. X    F_arc       *a;
  129. X    int            op;
  130. X{
  131. X    int            radius, rx, ry;
  132. X    int            xmin, ymin, xmax, ymax;
  133. X
  134. X    arc_bound(a, &xmin, &ymin, &xmax, &ymax);
  135. X    if (!overlapping(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax),
  136. X             clip_xmin, clip_ymin, clip_xmax, clip_ymax))
  137. X    return;
  138. X
  139. X    rx = a->point[0].x - a->center.x;
  140. X    ry = a->center.y - a->point[0].y;
  141. X    radius = round(sqrt((double) (rx * rx + ry * ry)));
  142. X
  143. X    curve(canvas_win, round(a->point[0].x - a->center.x),
  144. X      round(a->center.y - a->point[0].y),
  145. X      round(a->point[2].x - a->center.x),
  146. X      round(a->center.y - a->point[2].y),
  147. X      a->direction, 7*radius, radius, radius,
  148. X      round(a->center.x), round(a->center.y), op,
  149. X      a->thickness, a->style, a->style_val, a->fill_style, a->color);
  150. X
  151. X    draw_arcarrows(a, op);
  152. X}
  153. X
  154. X/*********************** ELLIPSE ***************************/
  155. X
  156. Xdraw_ellipse(e, op)
  157. X    F_ellipse       *e;
  158. X    int            op;
  159. X{
  160. X    int            a, b, xmin, ymin, xmax, ymax;
  161. X
  162. X    ellipse_bound(e, &xmin, &ymin, &xmax, &ymax);
  163. X    if (!overlapping(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax),
  164. X             clip_xmin, clip_ymin, clip_xmax, clip_ymax))
  165. X    return;
  166. X
  167. X    if (e->angle != 0.0) {
  168. X    angle_ellipse(e->center.x, e->center.y, e->radiuses.x, e->radiuses.y, 
  169. X        e->angle, op, e->thickness, e->style, 
  170. X        e->style_val, e->fill_style, e->color);
  171. X    /* it is much faster to use curve() for dashed and dotted lines that to
  172. X       use the server's sloooow algorithms for that */
  173. X    } else if (op != ERASE && (e->style == DOTTED_LINE || e->style == DASH_LINE)) {
  174. X    a = e->radiuses.x;
  175. X    b = e->radiuses.y;
  176. X    curve(canvas_win, a, 0, a, 0, e->direction, 7*max2(a,b), (b * b), (a * a),
  177. X          e->center.x, e->center.y, op,
  178. X          e->thickness, e->style, e->style_val, e->fill_style, e->color);
  179. X    /* however, for solid lines the server is muuuch faster even for thick lines */
  180. X    } else {
  181. X    xmin = e->center.x - e->radiuses.x;
  182. X    ymin = e->center.y - e->radiuses.y;
  183. X    xmax = e->center.x + e->radiuses.x;
  184. X    ymax = e->center.y + e->radiuses.y;
  185. X    pw_curve(canvas_win, xmin, ymin, xmax, ymax, op,
  186. X         e->thickness, e->style, e->style_val, e->fill_style,
  187. X         e->color);
  188. X    }
  189. X}
  190. X
  191. X/*
  192. X *  An Ellipse Generator.
  193. X *  Written by James Tough   7th May 92
  194. X *
  195. X *  The following routines displays a filled ellipse on the screen from the
  196. X *    semi-minor axis 'a', semi-major axis 'b' and angle of rotation
  197. X *    'phi'.
  198. X *
  199. X *  It works along these principles .....
  200. X *
  201. X *        The standard ellipse equation is
  202. X *
  203. X *             x*x     y*y
  204. X *             ---  +  ---
  205. X *             a*a     b*b
  206. X *
  207. X *
  208. X *        Rotation of a point (x,y) is well known through the use of
  209. X *
  210. X *            x' = x*COS(phi) - y*SIN(phi)
  211. X *            y' = y*COS(phi) + y*COS(phi)
  212. X *
  213. X *        Taking these to together, this gives the equation for a rotated
  214. X *      ellipse centered around the origin.
  215. X *
  216. X *           [x*COS(phi) - y*SIN(phi)]^2   [x*SIN(phi) + y*COS(phi)]^2
  217. X *           --------------------------- + ---------------------------
  218. X *                      a*a                           b*b
  219. X *
  220. X *        NOTE -  some of the above equation can be precomputed, eg,
  221. X *
  222. X *              i = COS(phi)/a        and        j = SIN(phi)/b
  223. X *       
  224. X *        NOTE -  y is constant for each line so,
  225. X *
  226. X *              m = -yk*SIN(phi)/a    and     n = yk*COS(phi)/b
  227. X *              where yk stands for the kth line ( y subscript k)
  228. X *
  229. X *        Where yk=y, we get a quadratic,
  230. X *
  231. X *              (i*x + m)^2 + (j*x + n)^2 = 1
  232. X *
  233. X *        Thus for any particular line, y, there is two corresponding x
  234. X *      values. These are the roots of the quadratic. To get the roots, 
  235. X *      the above equation can be rearranged using the standard method, 
  236. X *
  237. X *          -(i*m + j*n) +- sqrt[i^2 + j^2 - (i*n -j*m)^2]
  238. X *      x = ----------------------------------------------
  239. X *                           i^2 + j^2 
  240. X *
  241. X *        NOTE -  again much of this equation can be precomputed.
  242. X *     
  243. X *           c1 = i^2 + j^2 
  244. X *           c2 = [COS(phi)*SIN(phi)*(a-b)]
  245. X *           c3 = [b*b*(COS(phi)^2) + a*a*(SIN(phi)^2)]
  246. X *           c4 = a*b/c3
  247. X * 
  248. X *      x = c2*y +- c4*sqrt(c3 - y*y),    where +- must be evaluated once
  249. X *                                      for plus, and once for minus. 
  250. X *
  251. X *        We also need to know how large the ellipse is. This condition
  252. X *      arises when the sqrt of the above equation evaluates to zero.
  253. X *      Thus the height of the ellipse is give by 
  254. X * 
  255. X *              sqrt[ b*b*(COS(phi)^2) + a*a*(SIN(phi)^2) ]
  256. X *
  257. X *       which just happens to be equal to sqrt(c3).
  258. X *
  259. X *         It is now possible to create a routine that will scan convert 
  260. X *       the ellipse on the screen.
  261. X *
  262. X *        NOTE -  c2 is the gradient of the new ellipse axis.
  263. X *                c4 is the new semi-minor axis, 'a'.
  264. X *           sqr(c3) is the new semi-major axis, 'b'.
  265. X *
  266. X *         These values could be used in a 4WS or 8WS ellipse generator
  267. X *       that does not work on rotation, to give the feel of a rotated
  268. X *       ellipse. These ellipses are not very accurate and give visable
  269. X *       bumps along the edge of the ellipse. However, these routines
  270. X *       are very quick, and give a good approximation to a rotated ellipse.
  271. X *
  272. X *       NOTES on the code given.
  273. X * 
  274. X *           All the routines take there parameters as ( x, y, a, b, phi ),
  275. X *           where x,y are the center of the ellipse ( relative to the 
  276. X *           origin ), a and b are the vertical and horizontal axis, and
  277. X *           phi is the angle of rotation in RADIANS.
  278. X *
  279. X *           The 'moveto(x,y)' command moves the screen cursor to the 
  280. X *               (x,y) point.
  281. X *           The 'lineto(x,y)' command draws a line from the cursor to
  282. X *               the point (x,y).
  283. X *
  284. X *
  285. X *   Examples,
  286. X *
  287. X *       NOTE, all angles must be given in radians.
  288. X *
  289. X *       angle_ellipse(0,0,100,20,PI/4)         an ellipse at the origin,
  290. X *                                             major axis 100, minor 20
  291. X *                                             at angle 45 degrees.
  292. X *
  293. X *
  294. X */
  295. X
  296. X
  297. X/*
  298. X *  QuickEllipse, uses the same method as Ellipse, but uses incremental
  299. X *    methods to reduce the amount of work that has to be done inside
  300. X *    the main loop. The speed increase is very noticeable.
  301. X *
  302. X *  Written by James Tough
  303. X *  7th May 1992
  304. X * 
  305. X */
  306. X
  307. Xstatic int    x[MAXNUMPTS/4][4],y[MAXNUMPTS/4][4];
  308. Xstatic int    nump[4];
  309. Xstatic int    totpts,i,j;
  310. Xstatic int    order[4]={0,1,3,2};
  311. X
  312. Xangle_ellipse(center_x, center_y, radius_x, radius_y, angle,
  313. X          op, thickness, style, style_val, fill_style, color)
  314. X    int            center_x, center_y;
  315. X    int            radius_x, radius_y;
  316. X    float        angle;
  317. X    int            op,thickness,style,fill_style,color;
  318. X    float        style_val;
  319. X{
  320. X    float    xcen, ycen, a, b; 
  321. X
  322. X    double    c1, c2, c3, c4, c5, c6, v1, cphi, sphi, cphisqr, sphisqr;
  323. X    double    xleft, xright, d, asqr, bsqr;
  324. X    int    ymax, yy=0;
  325. X    int    k,m,dir;
  326. X    float    savezoom, savexoff, saveyoff;
  327. X    int    zoomthick;
  328. X    XPoint    *ipnts;
  329. X
  330. X    /* clear any previous error message */
  331. X    put_msg("");
  332. X    if (radius_x == 0 || radius_y == 0)
  333. X        return;
  334. X
  335. X    /* adjust for zoomscale so we iterate over zoomed pixels */
  336. X    xcen = ZOOMX(center_x);
  337. X    ycen = ZOOMY(center_y);
  338. X    a = radius_x*zoomscale;
  339. X    b = radius_y*zoomscale;
  340. X    zoomthick = round(zoomscale*thickness);
  341. X    if (zoomthick == 0 && thickness != 0)
  342. X        zoomthick=1;
  343. X    savezoom = zoomscale;
  344. X    savexoff = zoomxoff;
  345. X    saveyoff = zoomyoff;
  346. X    zoomscale = 1.0;
  347. X    zoomxoff = zoomyoff = 0.0;
  348. X
  349. X    cphi = cos((double)angle);
  350. X    sphi = sin((double)angle);
  351. X    cphisqr = cphi*cphi;
  352. X    sphisqr = sphi*sphi;
  353. X    asqr = a*a;
  354. X    bsqr = b*b;
  355. X    
  356. X    c1 = (cphisqr/asqr)+(sphisqr/bsqr);
  357. X    c2 = ((cphi*sphi/asqr)-(cphi*sphi/bsqr))/c1;
  358. X    c3 = (bsqr*cphisqr) + (asqr*sphisqr);
  359. X    ymax = sqrt(c3);
  360. X    c4 = a*b/c3;
  361. X    c5 = 0;
  362. X    v1 = c4*c4;
  363. X    c6 = 2*v1;
  364. X    c3 = c3*v1-v1;
  365. X    totpts = 0;
  366. X    for (i=0; i<=3; i++)
  367. X        nump[i]=0;
  368. X    i=0; j=0;
  369. X    /* odd first points */
  370. X    if (ymax % 2) {
  371. X        d = sqrt(c3);
  372. X        newpoint(xcen-d,ycen);
  373. X        newpoint(xcen+d,ycen);
  374. X        c5 = c2;
  375. X        yy=1;
  376. X    }
  377. X    while (c3>=0) {
  378. X        d = sqrt(c3);
  379. X        xleft = c5-d;
  380. X        xright = c5+d;                        
  381. X        newpoint(xcen+xleft,ycen+yy);
  382. X        newpoint(xcen+xright,ycen+yy);
  383. X        newpoint(xcen-xright,ycen-yy);
  384. X        newpoint(xcen-xleft,ycen-yy);
  385. X        c5+=c2;
  386. X        v1+=c6;
  387. X        c3-=v1;
  388. X        yy=yy+1;
  389. X    }
  390. X    dir=0;
  391. X    totpts++;    /* add another point to join with first */
  392. X    init_point_array(totpts, 0);
  393. X    ipnts = points;
  394. X    /* now go down the 1st column, up the 2nd, down the 4th 
  395. X       and up the 3rd to get the points in the correct order */
  396. X    for (k=0; k<=3; k++) {
  397. X        if (dir==0)
  398. X        for (m=0; m<nump[k]; m++) {
  399. X            add_point(x[m][order[k]],y[m][order[k]]);
  400. X        }
  401. X        else
  402. X        for (m=nump[k]-1; m>=0; m--) {
  403. X            add_point(x[m][order[k]],y[m][order[k]]);
  404. X        }
  405. X        dir = 1-dir;
  406. X    } /* next k */
  407. X    /* add another point to join with first */
  408. X    add_point(ipnts->x,ipnts->y);
  409. X    draw_point_array(canvas_win, op, zoomthick, style, style_val, 
  410. X         fill_style, color);
  411. X
  412. X    zoomscale = savezoom;
  413. X    zoomxoff = savexoff;
  414. X    zoomyoff = saveyoff;
  415. X    return;
  416. X}
  417. X
  418. X/* store the points across (row-wise in) the matrix */
  419. X
  420. Xnewpoint(xp,yp)
  421. X    float       xp,yp;
  422. X{
  423. X    if (totpts >= MAXNUMPTS/4) {
  424. X    if (totpts == MAXNUMPTS/4) {
  425. X        put_msg("Too many points to fully display rotated ellipse. %d points max",
  426. X        MAXNUMPTS);
  427. X        totpts++;
  428. X    }
  429. X    return;
  430. X    }
  431. X    x[i][j]=round(xp);
  432. X    y[i][j]=round(yp);
  433. X    nump[j]++;
  434. X    totpts++;
  435. X    if (++j > 3) {
  436. X    j=0; 
  437. X    i++;
  438. X    }
  439. X}
  440. X
  441. X
  442. X/*********************** LINE ***************************/
  443. X
  444. Xdraw_line(line, op)
  445. X    F_line       *line;
  446. X    int            op;
  447. X{
  448. X    F_point       *point;
  449. X    int            xx, yy, x, y;
  450. X    int            xmin, ymin, xmax, ymax;
  451. X    char       *string;
  452. X    F_point       *p0, *p1, *p2;
  453. X    pr_size        txt;
  454. X
  455. X    line_bound(line, &xmin, &ymin, &xmax, &ymax);
  456. X    if (!overlapping(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax),
  457. X             clip_xmin, clip_ymin, clip_xmax, clip_ymax))
  458. X    return;
  459. X
  460. X    /* is it an arcbox? */
  461. X    if (line->type == T_ARC_BOX) {
  462. X    draw_arcbox(line, op);
  463. X    return;
  464. X    }
  465. X    /* is it an eps file? */
  466. X    if (line->type == T_EPS_BOX) {
  467. X    if (line->eps->bitmap != NULL) {
  468. X        draw_eps_pixmap(line, op);
  469. X        return;
  470. X    } else {        /* label empty eps bounding box */
  471. X        if (line->eps->file[0] == '\0')
  472. X        string = EMPTY_EPS;
  473. X        else {
  474. X        string = rindex(line->eps->file, '/');
  475. X        if (string == NULL)
  476. X            string = line->eps->file;
  477. X        else
  478. X            string++;
  479. X        }
  480. X        p0 = line->points;
  481. X        p1 = p0->next;
  482. X        p2 = p1->next;
  483. X        xmin = min3(p0->x, p1->x, p2->x);
  484. X        ymin = min3(p0->y, p1->y, p2->y);
  485. X        xmax = max3(p0->x, p1->x, p2->x);
  486. X        ymax = max3(p0->y, p1->y, p2->y);
  487. X        canvas_font = lookfont(0, 12, 0.0);    /* get a size 12 font */
  488. X        txt = pf_textwidth(canvas_font, strlen(string), string);
  489. X        x = (xmin + xmax) / 2 - txt.x / 2;
  490. X        y = (ymin + ymax) / 2;
  491. X        pw_text(canvas_win, x, y, op, canvas_font, string, DEFAULT_COLOR);
  492. X        /* return; */
  493. X    }
  494. X    }
  495. X    /* get first point and coordinates */
  496. X    point = line->points;
  497. X    x = point->x;
  498. X    y = point->y;
  499. X
  500. X    /* is it a single point? */
  501. X    if (line->points->next == NULL) {
  502. X    /* draw but don't fill */
  503. X    pw_point(canvas_win, x, y, line->thickness, op, line->color);
  504. X    return;
  505. X    }
  506. X    if (line->back_arrow)    /* backward arrow  */
  507. X    draw_arrow(point->next->x, point->next->y, x, y,
  508. X           line->back_arrow, op, line->color);
  509. X
  510. X    /* accumulate the points in an array - start with 50 */
  511. X    if (!init_point_array(50, 50))
  512. X    return;
  513. X
  514. X    for (point = line->points; point != NULL; point = point->next) {
  515. X    xx = x;
  516. X    yy = y;
  517. X    x = point->x;
  518. X    y = point->y;
  519. X    add_point(x, y);
  520. X    }
  521. X
  522. X    draw_point_array(canvas_win, op, line->thickness, line->style,
  523. X             line->style_val, line->fill_style, line->color);
  524. X
  525. X    if (line->for_arrow)
  526. X    draw_arrow(xx, yy, x, y, line->for_arrow, op, line->color);
  527. X}
  528. X
  529. Xdraw_arcbox(line, op)
  530. X    F_line       *line;
  531. X    int            op;
  532. X{
  533. X    F_point       *point;
  534. X    int            xmin, xmax, ymin, ymax;
  535. X
  536. X    point = line->points;
  537. X    xmin = xmax = point->x;
  538. X    ymin = ymax = point->y;
  539. X    while (point->next) {    /* find lower left (upper-left on screen) */
  540. X    /* and upper right (lower right on screen) */
  541. X    point = point->next;
  542. X    if (point->x < xmin)
  543. X        xmin = point->x;
  544. X    else if (point->x > xmax)
  545. X        xmax = point->x;
  546. X    if (point->y < ymin)
  547. X        ymin = point->y;
  548. X    else if (point->y > ymax)
  549. X        ymax = point->y;
  550. X    }
  551. X    pw_arcbox(canvas_win, xmin, ymin, xmax, ymax, line->radius, op,
  552. X        line->thickness, line->style, line->style_val, line->fill_style,
  553. X          line->color);
  554. X}
  555. X
  556. Xdraw_eps_pixmap(box, op)
  557. X    F_line       *box;
  558. X    int            op;
  559. X{
  560. X    int            xmin, ymin;
  561. X    int            xmax, ymax;
  562. X    int            width, height, rotation;
  563. X    F_pos        origin;
  564. X    F_pos        opposite;
  565. X
  566. X    origin.x = ZOOMX(box->points->x);
  567. X    origin.y = ZOOMY(box->points->y);
  568. X    opposite.x = ZOOMX(box->points->next->next->x);
  569. X    opposite.y = ZOOMY(box->points->next->next->y);
  570. X
  571. X    xmin = min2(origin.x, opposite.x);
  572. X    ymin = min2(origin.y, opposite.y);
  573. X    xmax = max2(origin.x, opposite.x);
  574. X    ymax = max2(origin.y, opposite.y);
  575. X    if (op == ERASE) {
  576. X    clear_region(xmin, ymin, xmax, ymax);
  577. X    return;
  578. X    }
  579. X    width = abs(origin.x - opposite.x);
  580. X    height = abs(origin.y - opposite.y);
  581. X    rotation = 0;
  582. X    if (origin.x > opposite.x && origin.y > opposite.y)
  583. X    rotation = 180;
  584. X    if (origin.x > opposite.x && origin.y <= opposite.y)
  585. X    rotation = 270;
  586. X    if (origin.x <= opposite.x && origin.y > opposite.y)
  587. X    rotation = 90;
  588. X
  589. X    if (box->eps->pix_rotation != rotation ||
  590. X    box->eps->pix_width != width ||
  591. X    box->eps->pix_height != height ||
  592. X    box->eps->pix_flipped != box->eps->flipped)
  593. X    create_eps_pixmap(box, rotation, width, height, box->eps->flipped);
  594. X
  595. X    XCopyArea(tool_d, box->eps->pixmap, canvas_win, gccache[op],
  596. X          0, 0, xmax - xmin, ymax - ymin, xmin, ymin);
  597. X    XFlush(tool_d);
  598. X}
  599. X
  600. X/*
  601. X * The input to this routine is the bitmap which is the "preview"
  602. X * section of an encapsulated postscript file. That input bitmap
  603. X * has an arbitrary number of rows and columns. This routine
  604. X * re-samples the input bitmap creating an output bitmap of dimensions
  605. X * width-by-height. This output bitmap is made into an X-windows pixmap
  606. X * for display purposes.
  607. X */
  608. Xcreate_eps_pixmap(box, rotation, width, height, flipped)
  609. X    F_line       *box;
  610. X    int            rotation, width, height, flipped;
  611. X{
  612. X    int            i;
  613. X    int            j;
  614. X    byte       *data;
  615. X    byte       *tdata;
  616. X    int            nbytes;
  617. X    int            bbytes;
  618. X    int            ibit;
  619. X    int            jbit;
  620. X    int            wbit;
  621. X
  622. X    if (box->eps->pixmap != 0)
  623. X    XFreePixmap(tool_d, box->eps->pixmap);
  624. X
  625. X    nbytes = (width + 7) / 8;
  626. X    bbytes = (box->eps->bit_size.x + 7) / 8;
  627. X    data = (byte *) malloc(nbytes * height);
  628. X    tdata = (byte *) malloc(nbytes);
  629. X    bzero(data, nbytes * height);    /* clear memory */
  630. X
  631. X    /* create a new bitmap at the specified size (requires interpolation) */
  632. X    if ((!flipped && (rotation == 0 || rotation == 180)) ||
  633. X    (flipped && !(rotation == 0 || rotation == 180))) {
  634. X    for (j = 0; j < height; j++)
  635. X        for (i = 0; i < width; i++) {
  636. X        ibit = box->eps->bit_size.x * i / width;
  637. X        jbit = box->eps->bit_size.y * j / height;
  638. X        wbit = *(box->eps->bitmap + jbit * bbytes + ibit / 8);
  639. X        if (wbit & (1 << (7 - (ibit & 7))))
  640. X            *(data + j * nbytes + i / 8) += (1 << (i & 7));
  641. X        }
  642. X    } else {
  643. X    for (j = 0; j < height; j++)
  644. X        for (i = 0; i < width; i++) {
  645. X        ibit = box->eps->bit_size.x * j / height;
  646. X        jbit = box->eps->bit_size.y * i / width;
  647. X        wbit = *(box->eps->bitmap + jbit * bbytes + ibit / 8);
  648. X        if (wbit & (1 << (7 - (ibit & 7))))
  649. X            *(data + (height - j) * nbytes + i / 8) += (1 << (i & 7));
  650. X        }
  651. X    }
  652. X
  653. X    /* horizontal swap */
  654. X    if (rotation == 180 || rotation == 270)
  655. X    for (j = 0; j < height; j++) {
  656. X        bzero(tdata, nbytes);
  657. X        for (i = 0; i < width; i++)
  658. X        if (*(data + j * nbytes + (width - i - 1) / 8) & (1 << ((width - i - 1) & 7)))
  659. X            *(tdata + i / 8) += (1 << (i & 7));
  660. X        bcopy(tdata, data + j * nbytes, nbytes);
  661. X    }
  662. X
  663. X    /* vertical swap */
  664. X    if ((!flipped && (rotation == 180 || rotation == 270)) ||
  665. X    (flipped && !(rotation == 180 || rotation == 270)))
  666. X    for (j = 0; j < (height + 1) / 2; j++) {
  667. X        bcopy(data + j * nbytes, tdata, nbytes);
  668. X        bcopy(data + (height - j - 1) * nbytes, data + j * nbytes, nbytes);
  669. X        bcopy(tdata, data + (height - j - 1) * nbytes, nbytes);
  670. X    }
  671. X
  672. X    box->eps->pixmap = XCreatePixmapFromBitmapData(tool_d, canvas_win,
  673. X                           (char *) data, width, height,
  674. X                   (box->color >= 0 && box->color < NUMCOLORS) ?
  675. X                appres.color[box->color] : x_fg_color.pixel,
  676. X                           x_bg_color.pixel,
  677. X                          DefaultDepthOfScreen(tool_s));
  678. X    free(data);
  679. X    free(tdata);
  680. X
  681. X    box->eps->pix_rotation = rotation;
  682. X    box->eps->pix_width = width;
  683. X    box->eps->pix_height = height;
  684. X    box->eps->pix_flipped = flipped;
  685. X}
  686. X
  687. X/*********************** SPLINE ***************************/
  688. X
  689. Xdraw_spline(spline, op)
  690. X    F_spline       *spline;
  691. X    int            op;
  692. X{
  693. X    int            xmin, ymin, xmax, ymax;
  694. X
  695. X    spline_bound(spline, &xmin, &ymin, &xmax, &ymax);
  696. X    if (!overlapping(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax),
  697. X             clip_xmin, clip_ymin, clip_xmax, clip_ymax))
  698. X    return;
  699. X
  700. X    if (int_spline(spline))
  701. X    draw_intspline(spline, op);
  702. X    else if (spline->type == T_CLOSED_NORMAL)
  703. X    draw_closed_spline(spline, op);
  704. X    else if (spline->type == T_OPEN_NORMAL)
  705. X    draw_open_spline(spline, op);
  706. X}
  707. X
  708. Xdraw_intspline(s, op)
  709. X    F_spline       *s;
  710. X    int            op;
  711. X{
  712. X    F_point       *p1, *p2;
  713. X    F_control       *cp1, *cp2;
  714. X
  715. X    p1 = s->points;
  716. X    cp1 = s->controls;
  717. X    cp2 = cp1->next;
  718. X    if (s->back_arrow)
  719. X    draw_arrow(round(cp2->lx), round(cp2->ly), p1->x, p1->y,
  720. X           s->back_arrow, op, s->color);
  721. X
  722. X    if (!init_point_array(300, 200))
  723. X    return;
  724. X
  725. X    for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  726. X     p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  727. X    bezier_spline((float) p1->x, (float) p1->y, cp1->rx, cp1->ry,
  728. X              cp2->lx, cp2->ly, (float) p2->x, (float) p2->y, op,
  729. X              s->thickness, s->style, s->style_val);
  730. X    }
  731. X
  732. X    add_point(p1->x, p1->y);
  733. X
  734. X    draw_point_array(canvas_win, op, s->thickness, s->style,
  735. X             s->style_val, s->fill_style, s->color);
  736. X
  737. X    if (s->for_arrow)
  738. X    draw_arrow(round(cp1->lx), round(cp1->ly), p1->x,
  739. X           p1->y, s->for_arrow, op, s->color);
  740. X}
  741. X
  742. Xdraw_open_spline(spline, op)
  743. X    F_spline       *spline;
  744. X    int            op;
  745. X{
  746. X    F_point       *p;
  747. X    float        cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  748. X    float        x1, y1, x2, y2;
  749. X
  750. X    if (!init_point_array(300, 200))
  751. X    return;
  752. X
  753. X    p = spline->points;
  754. X    x1 = p->x;
  755. X    y1 = p->y;
  756. X    p = p->next;
  757. X    x2 = p->x;
  758. X    y2 = p->y;
  759. X    cx1 = (x1 + x2) / 2;
  760. X    cy1 = (y1 + y2) / 2;
  761. X    cx2 = (cx1 + x2) / 2;
  762. X    cy2 = (cy1 + y2) / 2;
  763. X    if (spline->back_arrow)    /* backward arrow  */
  764. X    draw_arrow((int) x2, (int) y2, (int) x1, (int) y1,
  765. X           spline->back_arrow, op, spline->color);
  766. X    add_point((int) x1, (int) y1);
  767. X
  768. X    for (p = p->next; p != NULL; p = p->next) {
  769. X    x1 = x2;
  770. X    y1 = y2;
  771. X    x2 = p->x;
  772. X    y2 = p->y;
  773. X    cx4 = (x1 + x2) / 2;
  774. X    cy4 = (y1 + y2) / 2;
  775. X    cx3 = (x1 + cx4) / 2;
  776. X    cy3 = (y1 + cy4) / 2;
  777. X    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4, op,
  778. X             spline->thickness, spline->style, spline->style_val,
  779. X             spline->color);
  780. X    cx1 = cx4;
  781. X    cy1 = cy4;
  782. X    cx2 = (cx1 + x2) / 2;
  783. X    cy2 = (cy1 + y2) / 2;
  784. X    }
  785. X
  786. X    add_point(round(cx1), round(cy1));
  787. X    add_point((int) x2, (int) y2);
  788. X
  789. X    draw_point_array(canvas_win, op, spline->thickness, spline->style,
  790. X             spline->style_val, spline->fill_style, spline->color);
  791. X
  792. X    if (spline->for_arrow)    /* forward arrow  */
  793. X    draw_arrow((int) x1, (int) y1, (int) x2, (int) y2,
  794. X           spline->for_arrow, op, spline->color);
  795. X}
  796. X
  797. Xdraw_closed_spline(spline, op)
  798. X    F_spline       *spline;
  799. X    int            op;
  800. X{
  801. X    F_point       *p;
  802. X    float        cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  803. X    float        x1, y1, x2, y2;
  804. X
  805. X    if (!init_point_array(300, 200))
  806. X    return;
  807. X
  808. X    p = spline->points;
  809. X    x1 = p->x;
  810. X    y1 = p->y;
  811. X    p = p->next;
  812. X    x2 = p->x;
  813. X    y2 = p->y;
  814. X    cx1 = (x1 + x2) / 2;
  815. X    cy1 = (y1 + y2) / 2;
  816. X    cx2 = (x1 + 3 * x2) / 4;
  817. X    cy2 = (y1 + 3 * y2) / 4;
  818. X
  819. X    for (p = p->next; p != NULL; p = p->next) {
  820. X    x1 = x2;
  821. X    y1 = y2;
  822. X    x2 = p->x;
  823. X    y2 = p->y;
  824. X    cx4 = (x1 + x2) / 2;
  825. X    cy4 = (y1 + y2) / 2;
  826. X    cx3 = (x1 + cx4) / 2;
  827. X    cy3 = (y1 + cy4) / 2;
  828. X    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4, op,
  829. X             spline->thickness, spline->style, spline->style_val,
  830. X             spline->color);
  831. X    cx1 = cx4;
  832. X    cy1 = cy4;
  833. X    cx2 = (cx1 + x2) / 2;
  834. X    cy2 = (cy1 + y2) / 2;
  835. X    }
  836. X    x1 = x2;
  837. X    y1 = y2;
  838. X    p = spline->points->next;
  839. X    x2 = p->x;
  840. X    y2 = p->y;
  841. X    cx4 = (x1 + x2) / 2;
  842. X    cy4 = (y1 + y2) / 2;
  843. X    cx3 = (x1 + cx4) / 2;
  844. X    cy3 = (y1 + cy4) / 2;
  845. X    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4, op,
  846. X             spline->thickness, spline->style, spline->style_val,
  847. X             spline->color);
  848. X
  849. X    add_point((int) cx4, (int) cy4);
  850. X
  851. X    draw_point_array(canvas_win, op, spline->thickness, spline->style,
  852. X             spline->style_val, spline->fill_style, spline->color);
  853. X}
  854. X
  855. X
  856. X/*********************** TEXT ***************************/
  857. X
  858. Xstatic char    *hidden_text_string = "<<>>";
  859. X
  860. Xdraw_text(text, op)
  861. X    F_text       *text;
  862. X    int            op;
  863. X{
  864. X    PR_SIZE        size;
  865. X    int            x,y;
  866. X    float        angle;
  867. X    int            xmin, ymin, xmax, ymax;
  868. X    int            x1,y1, x2,y2, x3,y3, x4,y4;
  869. X
  870. X    if (appres.textoutline)    /* get corners of rectangle at actual angle */
  871. X    text_bound_both(text, &xmin, &ymin, &xmax, &ymax, 
  872. X              &x1,&y1, &x2,&y2, &x3,&y3, &x4,&y4);
  873. X    else
  874. X    text_bound(text, &xmin, &ymin, &xmax, &ymax);
  875. X
  876. X    if (!overlapping(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax),
  877. X             clip_xmin, clip_ymin, clip_xmax, clip_ymax))
  878. X    return;
  879. X
  880. X    /* outline the text bounds in red if textoutline resource is set */
  881. X    if (appres.textoutline && !hidden_text(text)) {
  882. X    pw_vector(canvas_win, x1, y1, x2, y2, op, 1, RUBBER_LINE, 0.0, 4);
  883. X    pw_vector(canvas_win, x2, y2, x3, y3, op, 1, RUBBER_LINE, 0.0, 4);
  884. X    pw_vector(canvas_win, x3, y3, x4, y4, op, 1, RUBBER_LINE, 0.0, 4);
  885. X    pw_vector(canvas_win, x4, y4, x1, y1, op, 1, RUBBER_LINE, 0.0, 4);
  886. X    }
  887. X
  888. X    x = text->base_x;
  889. X    y = text->base_y;
  890. X    angle = text->angle*180.0/M_PI;
  891. X    if (text->type == T_CENTER_JUSTIFIED || text->type == T_RIGHT_JUSTIFIED) {
  892. X    size = pf_textwidth(text->fontstruct, strlen(text->cstring), 
  893. X                text->cstring);
  894. X    size.x = size.x/zoomscale;
  895. X    if (text->type == T_CENTER_JUSTIFIED) {
  896. X        if (angle < 90.0 - 0.001)
  897. X        x -= size.x / 2;    /*   0 to  89 degrees */
  898. X        else if (angle < 180.0 - 0.001)
  899. X        y += size.x / 2;    /*  90 to 179 degrees */
  900. X        else if (angle < 270.0 - 0.001)
  901. X        x += size.x / 2;    /* 180 to 269 degrees */
  902. X        else 
  903. X        y -= size.x / 2;    /* 270 to 359 degrees */
  904. X
  905. X    } else {    /* T_RIGHT_JUSTIFIED */
  906. X        if (angle < 90.0 - 0.001)
  907. X        x -= size.x;        /*   0 to  89 degrees */
  908. X        else if (angle < 180.0 - 0.001)
  909. X        y += size.x;        /*  90 to 179 degrees */
  910. X        else if (angle < 270.0 - 0.001)
  911. X        x += size.x;        /* 180 to 269 degrees */
  912. X        else 
  913. X        y -= size.x;        /* 270 to 359 degrees */
  914. X    }
  915. X    }
  916. X    if (hidden_text(text))
  917. X    pw_text(canvas_win, x, y, op, lookfont(0,12,text->angle),
  918. X        hidden_text_string, DEFAULT_COLOR);
  919. X    else
  920. X    pw_text(canvas_win, x, y, op, text->fontstruct,
  921. X        text->cstring, text->color);
  922. X}
  923. X
  924. X/*********************** COMPOUND ***************************/
  925. X
  926. Xvoid
  927. Xdraw_compoundelements(c, op)
  928. X    F_compound       *c;
  929. X    int            op;
  930. X{
  931. X    F_line       *l;
  932. X    F_spline       *s;
  933. X    F_ellipse       *e;
  934. X    F_text       *t;
  935. X    F_arc       *a;
  936. X    F_compound       *c1;
  937. X
  938. X    if (!overlapping(ZOOMX(c->nwcorner.x), ZOOMY(c->nwcorner.y), 
  939. X             ZOOMX(c->secorner.x), ZOOMY(c->secorner.y),
  940. X             clip_xmin, clip_ymin, clip_xmax, clip_ymax))
  941. X    return;
  942. X
  943. X    for (l = c->lines; l != NULL; l = l->next) {
  944. X    draw_line(l, op);
  945. X    }
  946. X    for (s = c->splines; s != NULL; s = s->next) {
  947. X    draw_spline(s, op);
  948. X    }
  949. X    for (a = c->arcs; a != NULL; a = a->next) {
  950. X    draw_arc(a, op);
  951. X    }
  952. X    for (e = c->ellipses; e != NULL; e = e->next) {
  953. X    draw_ellipse(e, op);
  954. X    }
  955. X    for (t = c->texts; t != NULL; t = t->next) {
  956. X    draw_text(t, op);
  957. X    }
  958. X    for (c1 = c->compounds; c1 != NULL; c1 = c1->next) {
  959. X    draw_compoundelements(c1, op);
  960. X    }
  961. X}
  962. X
  963. X/*************************** ARROWS ****************************
  964. X
  965. X draw arrow heading from (x1, y1) to (x2, y2)
  966. X
  967. X****************************************************************/
  968. X
  969. Xdraw_arrow(x1, y1, x2, y2, arrow, op, color)
  970. X    int            x1, y1, x2, y2, op;
  971. X    F_arrow       *arrow;
  972. X    Color        color;
  973. X{
  974. X    float        x, y, xb, yb, dx, dy, l, sina, cosa;
  975. X    int            xc, yc, xd, yd;
  976. X    float        wid = arrow->wid, ht = arrow->ht;
  977. X
  978. X    dx = x2 - x1;
  979. X    dy = y1 - y2;
  980. X    l = sqrt((double) (dx * dx + dy * dy));
  981. X    if (l == 0)
  982. X    return;
  983. X    sina = dy / l;
  984. X    cosa = dx / l;
  985. X    xb = x2 * cosa - y2 * sina;
  986. X    yb = x2 * sina + y2 * cosa;
  987. X    x = xb - ht;
  988. X    y = yb - wid / 2;
  989. X    xc = x * cosa + y * sina + .5;
  990. X    yc = -x * sina + y * cosa + .5;
  991. X    y = yb + wid / 2;
  992. X    xd = x * cosa + y * sina + .5;
  993. X    yd = -x * sina + y * cosa + .5;
  994. X    pw_vector(canvas_win, xc, yc, x2, y2, op,
  995. X          (int) arrow->thickness, arrow->style, 0.0, color);
  996. X    pw_vector(canvas_win, xd, yd, x2, y2, op,
  997. X          (int) arrow->thickness, arrow->style, 0.0, color);
  998. X}
  999. X
  1000. Xdraw_arcarrows(a, op)
  1001. X    F_arc       *a;
  1002. X    int            op;
  1003. X{
  1004. X    int            x, y;
  1005. X
  1006. X    if (a->for_arrow) {
  1007. X    compute_normal(a->center.x, a->center.y, a->point[2].x,
  1008. X               a->point[2].y, a->direction, &x, &y);
  1009. X    draw_arrow(x, y, a->point[2].x, a->point[2].y, a->for_arrow, op,
  1010. X           a->color);
  1011. X    }
  1012. X    if (a->back_arrow) {
  1013. X    compute_normal(a->center.x, a->center.y, a->point[0].x,
  1014. X               a->point[0].y, a->direction ^ 1, &x, &y);
  1015. X    draw_arrow(x, y, a->point[0].x, a->point[0].y,
  1016. X           a->back_arrow, op, a->color);
  1017. X    }
  1018. X}
  1019. X
  1020. X/********************* CURVES FOR ARCS AND ELLIPSES ***************
  1021. X
  1022. X This routine plot two dimensional curve defined by a second degree
  1023. X polynomial of the form : 2    2 f(x, y) = ax + by + g = 0
  1024. X
  1025. X (x0,y0) is the starting point as well as ending point of the curve. The curve
  1026. X will translate with the offset xoff and yoff.
  1027. X
  1028. X This algorithm is derived from the eight point algorithm in : "An Improved
  1029. X Algorithm for the generation of Nonparametric Curves" by Bernard W.
  1030. X Jordan, William J. Lennon and Barry D. Holm, IEEE Transaction on Computers
  1031. X Vol C-22, No. 12 December 1973.
  1032. X
  1033. X Will fill the curve if fill_style is != 0
  1034. X
  1035. X****************************************************************/
  1036. X
  1037. Xcurve(window, xstart, ystart, xend, yend, direction, estnpts,
  1038. X      a, b, xoff, yoff, op, thick, style, style_val, fill_style, color)
  1039. X    Window        window;
  1040. X    int            xstart, ystart, xend, yend, a, b, xoff, yoff;
  1041. X    int            direction, estnpts, op, thick, style, fill_style;
  1042. X    float        style_val;
  1043. X    int            color;
  1044. X{
  1045. X    register int    deltax, deltay, dfx, dfy, x, y;
  1046. X    int            dfxx, dfyy;
  1047. X    int            falpha, fx, fy, fxy, absfx, absfy, absfxy;
  1048. X    int            margin, test_succeed, inc, dec;
  1049. X
  1050. X    if (a == 0 || b == 0)
  1051. X    return;
  1052. X
  1053. X    if (!init_point_array(estnpts,estnpts/2)) /* estimate of number of points */
  1054. X    return;
  1055. X
  1056. X    x = xstart;
  1057. X    y = ystart;
  1058. X    dfx = 2 * a * xstart;
  1059. X    dfy = 2 * b * ystart;
  1060. X    dfxx = 2 * a;
  1061. X    dfyy = 2 * b;
  1062. X
  1063. X    falpha = 0;
  1064. X    if (direction) {
  1065. X    inc = 1;
  1066. X    dec = -1;
  1067. X    } else {
  1068. X    inc = -1;
  1069. X    dec = 1;
  1070. X    }
  1071. X    if (xstart == xend && ystart == yend) {
  1072. X    test_succeed = margin = 1;
  1073. X    } else {
  1074. X    test_succeed = margin = 1;
  1075. X    }
  1076. X
  1077. X    if (!add_point(xoff + x, yoff - y))
  1078. X    /* (error) */ ;
  1079. X    else
  1080. X      while (test_succeed) {
  1081. X    deltax = (dfy < 0) ? inc : dec;
  1082. X    deltay = (dfx < 0) ? dec : inc;
  1083. X    fx = falpha + dfx * deltax + a;
  1084. X    fy = falpha + dfy * deltay + b;
  1085. X    fxy = fx + fy - falpha;
  1086. X    absfx = abs(fx);
  1087. X    absfy = abs(fy);
  1088. X    absfxy = abs(fxy);
  1089. X
  1090. X    if ((absfxy <= absfx) && (absfxy <= absfy))
  1091. X        falpha = fxy;
  1092. X    else if (absfy <= absfx) {
  1093. X        deltax = 0;
  1094. X        falpha = fy;
  1095. X    } else {
  1096. X        deltay = 0;
  1097. X        falpha = fx;
  1098. X    }
  1099. X    x += deltax;
  1100. X    y += deltay;
  1101. X    dfx += (dfxx * deltax);
  1102. X    dfy += (dfyy * deltay);
  1103. X    if (!add_point(xoff + x, yoff - y))
  1104. X        break;
  1105. X
  1106. X    if (abs(x - xend) < margin && abs(y - yend) < margin)
  1107. X        test_succeed--;
  1108. X    }
  1109. X
  1110. X    if (xstart == xend && ystart == yend)    /* end points should touch */
  1111. X    add_point(xoff + xstart, yoff - ystart);
  1112. X
  1113. X    draw_point_array(window, op, thick, style, style_val, fill_style, color);
  1114. X}
  1115. X
  1116. X/********************* CURVES FOR SPLINES *****************************
  1117. X
  1118. X    The following spline drawing routine is from
  1119. X
  1120. X    "An Algorithm for High-Speed Curve Generation"
  1121. X    by George Merrill Chaikin,
  1122. X    Computer Graphics and Image Processing, 3, Academic Press,
  1123. X    1974, 346-349.
  1124. X
  1125. X    and
  1126. X
  1127. X    "On Chaikin's Algorithm" by R. F. Riesenfeld,
  1128. X    Computer Graphics and Image Processing, 4, Academic Press,
  1129. X    1975, 304-310.
  1130. X
  1131. X***********************************************************************/
  1132. X
  1133. X#define        half(z1, z2)    ((z1+z2)/2.0)
  1134. X#define        THRESHOLD    5
  1135. X
  1136. X/* iterative version */
  1137. X/*
  1138. X * because we draw the spline with small line segments, the style parameter
  1139. X * doesn't work
  1140. X */
  1141. X
  1142. Xquadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4, op, thick, style,
  1143. X         style_val, color)
  1144. X    float        a1, b1, a2, b2, a3, b3, a4, b4;
  1145. X    int            op, thick, style;
  1146. X    float        style_val;
  1147. X    int            color;
  1148. X{
  1149. X    register float  xmid, ymid;
  1150. X    float        x1, y1, x2, y2, x3, y3, x4, y4;
  1151. X
  1152. X    clear_stack();
  1153. X    push(a1, b1, a2, b2, a3, b3, a4, b4);
  1154. X
  1155. X    while (pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
  1156. X    xmid = half(x2, x3);
  1157. X    ymid = half(y2, y3);
  1158. X    if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
  1159. X        fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
  1160. X        add_point(round(x1), round(y1));
  1161. X        add_point(round(xmid), round(ymid));
  1162. X    } else {
  1163. X        push(xmid, ymid, half(xmid, x3), half(ymid, y3),
  1164. X         half(x3, x4), half(y3, y4), x4, y4);
  1165. X        push(x1, y1, half(x1, x2), half(y1, y2),
  1166. X         half(x2, xmid), half(y2, ymid), xmid, ymid);
  1167. X    }
  1168. X    }
  1169. X}
  1170. X
  1171. X/*
  1172. X * the style parameter doesn't work for splines because we use small line
  1173. X * segments
  1174. X */
  1175. X
  1176. Xbezier_spline(a0, b0, a1, b1, a2, b2, a3, b3, op, thick, style, style_val)
  1177. X    float        a0, b0, a1, b1, a2, b2, a3, b3;
  1178. X    int            op, thick, style;
  1179. X    float        style_val;
  1180. X{
  1181. X    register float  tx, ty;
  1182. X    float        x0, y0, x1, y1, x2, y2, x3, y3;
  1183. X    float        sx1, sy1, sx2, sy2, tx1, ty1, tx2, ty2, xmid, ymid;
  1184. X
  1185. X    clear_stack();
  1186. X    push(a0, b0, a1, b1, a2, b2, a3, b3);
  1187. X
  1188. X    while (pop(&x0, &y0, &x1, &y1, &x2, &y2, &x3, &y3)) {
  1189. X    if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD) {
  1190. X        add_point(round(x0), round(y0));
  1191. X    } else {
  1192. X        tx = half(x1, x2);
  1193. X        ty = half(y1, y2);
  1194. X        sx1 = half(x0, x1);
  1195. X        sy1 = half(y0, y1);
  1196. X        sx2 = half(sx1, tx);
  1197. X        sy2 = half(sy1, ty);
  1198. X        tx2 = half(x2, x3);
  1199. X        ty2 = half(y2, y3);
  1200. X        tx1 = half(tx2, tx);
  1201. X        ty1 = half(ty2, ty);
  1202. X        xmid = half(sx2, tx1);
  1203. X        ymid = half(sy2, ty1);
  1204. X
  1205. X        push(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  1206. X        push(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  1207. X    }
  1208. X    }
  1209. X}
  1210. X
  1211. X/* utilities used by spline drawing routines */
  1212. X
  1213. X#define        STACK_DEPTH        20
  1214. X
  1215. Xtypedef struct stack {
  1216. X    float        x1, y1, x2, y2, x3, y3, x4, y4;
  1217. X}
  1218. X        Stack;
  1219. X
  1220. Xstatic Stack    stack[STACK_DEPTH];
  1221. Xstatic Stack   *stack_top;
  1222. Xstatic int    stack_count;
  1223. X
  1224. Xclear_stack()
  1225. X{
  1226. X    stack_top = stack;
  1227. X    stack_count = 0;
  1228. X}
  1229. X
  1230. Xpush(x1, y1, x2, y2, x3, y3, x4, y4)
  1231. X    float        x1, y1, x2, y2, x3, y3, x4, y4;
  1232. X{
  1233. X    stack_top->x1 = x1;
  1234. X    stack_top->y1 = y1;
  1235. X    stack_top->x2 = x2;
  1236. X    stack_top->y2 = y2;
  1237. X    stack_top->x3 = x3;
  1238. X    stack_top->y3 = y3;
  1239. X    stack_top->x4 = x4;
  1240. X    stack_top->y4 = y4;
  1241. X    stack_top++;
  1242. X    stack_count++;
  1243. X}
  1244. X
  1245. Xint
  1246. Xpop(x1, y1, x2, y2, x3, y3, x4, y4)
  1247. X    float       *x1, *y1, *x2, *y2, *x3, *y3, *x4, *y4;
  1248. X{
  1249. X    if (stack_count == 0)
  1250. X    return (0);
  1251. X    stack_top--;
  1252. X    stack_count--;
  1253. X    *x1 = stack_top->x1;
  1254. X    *y1 = stack_top->y1;
  1255. X    *x2 = stack_top->x2;
  1256. X    *y2 = stack_top->y2;
  1257. X    *x3 = stack_top->x3;
  1258. X    *y3 = stack_top->y3;
  1259. X    *x4 = stack_top->x4;
  1260. X    *y4 = stack_top->y4;
  1261. X    return (1);
  1262. X}
  1263. END_OF_FILE
  1264. if test 34170 -ne `wc -c <'u_draw.c'`; then
  1265.     echo shar: \"'u_draw.c'\" unpacked with wrong size!
  1266. fi
  1267. # end of 'u_draw.c'
  1268. fi
  1269. if test -f 'w_rulers.c' -a "${1}" != "-c" ; then 
  1270.   echo shar: Will not clobber existing file \"'w_rulers.c'\"
  1271. else
  1272. echo shar: Extracting \"'w_rulers.c'\" \(31896 characters\)
  1273. sed "s/^X//" >'w_rulers.c' <<'END_OF_FILE'
  1274. X/*
  1275. X * FIG : Facility for Interactive Generation of figures
  1276. X * Copyright (c) 1985 by Supoj Sutanthavibul
  1277. X *
  1278. X * "Permission to use, copy, modify, distribute, and sell this software and its
  1279. X * documentation for any purpose is hereby granted without fee, provided that
  1280. X * the above copyright notice appear in all copies and that both the copyright
  1281. X * notice and this permission notice appear in supporting documentation. 
  1282. X * No representations are made about the suitability of this software for 
  1283. X * any purpose.  It is provided "as is" without express or implied warranty."
  1284. X */
  1285. X
  1286. X#include "fig.h"
  1287. X#include "figx.h"
  1288. X#include "resources.h"
  1289. X#include "mode.h"
  1290. X#include "paintop.h"
  1291. X#include "w_drawprim.h"
  1292. X#include "w_mousefun.h"
  1293. X#include "w_setup.h"
  1294. X#include "w_util.h"
  1295. X#include "w_zoom.h"
  1296. X
  1297. X/*
  1298. X * The following will create rulers the same size as the initial screen size.
  1299. X * if the user resizes the xfig window, the rulers won't have numbers there.
  1300. X * Should really reset the sizes if the screen resizes.
  1301. X */
  1302. X
  1303. X/*
  1304. X * set maximum ruler size:
  1305. X * color servers for Vaxstations screw up the pixmaps if the rulers are
  1306. X * made too big (they can't handle pixmaps much larger than the screen)
  1307. X */
  1308. X
  1309. X#define            INCH_MARK        8
  1310. X#define            HALF_MARK        8
  1311. X#define            QUARTER_MARK        6
  1312. X#define            SIXTEENTH_MARK        4
  1313. X
  1314. X#define            TRM_WID            16
  1315. X#define            TRM_HT            8
  1316. X#define            SRM_WID            8
  1317. X#define            SRM_HT            16
  1318. X
  1319. Xextern        pan_origin();
  1320. XGC        tr_gc, tr_xor_gc, tr_erase_gc;
  1321. XGC        sr_gc, sr_xor_gc, sr_erase_gc;
  1322. X
  1323. Xstatic int    lasty = -100, lastx = -100;
  1324. Xstatic int    troffx = -8, troffy = -10;
  1325. Xstatic int    orig_zoomoff;
  1326. Xstatic int    last_drag_x, last_drag_y;
  1327. Xstatic unsigned char    tr_marker_image[16] = {
  1328. X    0xFE, 0xFF,        /* ***************  */
  1329. X    0x04, 0x40,        /*  *           *  */
  1330. X    0x08, 0x20,        /*   *         *  */
  1331. X    0x10, 0x10,        /*    *       *  */
  1332. X    0x20, 0x08,        /*     *     *  */
  1333. X    0x40, 0x04,        /*      *   *  */
  1334. X    0x80, 0x02,        /*       * *  */
  1335. X    0x00, 0x01,        /*        *  */
  1336. X};
  1337. Xstatic        mpr_static(trm_pr, TRM_WID, TRM_HT, 1, tr_marker_image);
  1338. Xstatic int    srroffx = 2, srroffy = -7;
  1339. Xstatic unsigned char    srr_marker_image[16] = {
  1340. X    0x80,        /*        *  */
  1341. X    0xC0,        /*       **  */
  1342. X    0xA0,        /*      * *  */
  1343. X    0x90,        /*     *  *  */
  1344. X    0x88,        /*    *   *  */
  1345. X    0x84,        /*   *    *  */
  1346. X    0x82,        /*  *     *  */
  1347. X    0x81,        /* *      *  */
  1348. X    0x82,        /*  *     *  */
  1349. X    0x84,        /*   *    *  */
  1350. X    0x88,        /*    *   *  */
  1351. X    0x90,        /*     *  *  */
  1352. X    0xA0,        /*      * *  */
  1353. X    0xC0,        /*       **  */
  1354. X    0x80,        /*        *  */
  1355. X    0x00
  1356. X};
  1357. Xstatic        mpr_static(srrm_pr, SRM_WID, SRM_HT, 1, srr_marker_image);
  1358. X
  1359. Xstatic int    srloffx = -10, srloffy = -7;
  1360. Xstatic unsigned char    srl_marker_image[16] = {
  1361. X    0x01,        /* *          */
  1362. X    0x03,        /* **          */
  1363. X    0x05,        /* * *          */
  1364. X    0x09,        /* *  *          */
  1365. X    0x11,        /* *   *      */
  1366. X    0x21,        /* *    *     */
  1367. X    0x41,        /* *     *    */
  1368. X    0x81,        /* *      *   */
  1369. X    0x41,        /* *     *    */
  1370. X    0x21,        /* *    *     */
  1371. X    0x11,        /* *   *      */
  1372. X    0x09,        /* *  *          */
  1373. X    0x05,        /* * *          */
  1374. X    0x03,        /* **          */
  1375. X    0x01,        /* *          */
  1376. X    0x00
  1377. X};
  1378. Xstatic        mpr_static(srlm_pr, SRM_WID, SRM_HT, 1, srl_marker_image);
  1379. X
  1380. Xstatic Pixmap    toparrow_pm = 0, sidearrow_pm = 0;
  1381. Xstatic Pixmap    topruler_pm = 0, sideruler_pm = 0;
  1382. X
  1383. XDeclareStaticArgs(14);
  1384. X
  1385. Xstatic        topruler_selected();
  1386. Xstatic        topruler_exposed();
  1387. Xstatic        sideruler_selected();
  1388. Xstatic        sideruler_exposed();
  1389. X
  1390. Xredisplay_rulers()
  1391. X{
  1392. X    redisplay_topruler();
  1393. X    redisplay_sideruler();
  1394. X}
  1395. X
  1396. Xsetup_rulers()
  1397. X{
  1398. X    setup_topruler();
  1399. X    setup_sideruler();
  1400. X}
  1401. X
  1402. Xreset_rulers()
  1403. X{
  1404. X    reset_topruler();
  1405. X    reset_sideruler();
  1406. X}
  1407. X
  1408. Xset_rulermark(x, y)
  1409. X    int            x, y;
  1410. X{
  1411. X    if (appres.TRACKING) {
  1412. X    set_siderulermark(y);
  1413. X    set_toprulermark(x);
  1414. X    }
  1415. X}
  1416. X
  1417. Xerase_rulermark()
  1418. X{
  1419. X    if (appres.TRACKING) {
  1420. X    erase_siderulermark();
  1421. X    erase_toprulermark();
  1422. X    }
  1423. X}
  1424. X
  1425. X#define HINCH    (PIX_PER_INCH / 2)
  1426. X#define QINCH    (PIX_PER_INCH / 4)
  1427. X#define SINCH    (PIX_PER_INCH / 16)
  1428. X#define TWOMM    (PIX_PER_CM / 5)
  1429. X
  1430. X/************************* UNITBOX ************************/
  1431. X
  1432. Xextern Widget   make_popup_menu();
  1433. Xextern Atom     wm_delete_window;
  1434. Xextern char    *panel_get_value();
  1435. Xvoid popup_unit_panel();
  1436. Xstatic int      rul_unit_setting, fig_unit_setting=0, fig_scale_setting=0;
  1437. Xstatic Widget   rul_unit_panel, fig_unit_panel, fig_scale_panel;
  1438. Xstatic Widget   rul_unit_menu, fig_unit_menu, fig_scale_menu;
  1439. Xstatic Widget   scale_factor_lab, scale_factor_panel;
  1440. Xstatic Widget   user_unit_lab, user_unit_panel;
  1441. X
  1442. X
  1443. XXtActionsRec    unitbox_actions[] =
  1444. X{
  1445. X    {"EnterUnitBox", (XtActionProc) draw_mousefun_unitbox},
  1446. X    {"LeaveUnitBox", (XtActionProc) clear_mousefun},
  1447. X    {"HomeRulers", (XtActionProc) pan_origin},
  1448. X    {"PopupUnits", (XtActionProc) popup_unit_panel},
  1449. X};
  1450. X
  1451. Xstatic String    unitbox_translations =
  1452. X"<EnterWindow>:EnterUnitBox()\n\
  1453. X    <LeaveWindow>:LeaveUnitBox()\n\
  1454. X    <Btn1Down>:HomeRulers()\n\
  1455. X    <Btn3Down>:PopupUnits()\n";
  1456. X
  1457. Xint
  1458. Xinit_unitbox(tool)
  1459. X    TOOL        tool;
  1460. X{
  1461. X    FirstArg(XtNwidth, SIDERULER_WD);
  1462. X    NextArg(XtNheight, RULER_WD);
  1463. X    NextArg(XtNlabel, appres.INCHES ? "in" : "cm");
  1464. X    NextArg(XtNfont, button_font);
  1465. X    NextArg(XtNfromHoriz, canvas_sw);
  1466. X    NextArg(XtNhorizDistance, -INTERNAL_BW);
  1467. X    NextArg(XtNfromVert, msg_form);
  1468. X    NextArg(XtNvertDistance, -INTERNAL_BW);
  1469. X    NextArg(XtNresizable, False);
  1470. X    NextArg(XtNtop, XtChainTop);
  1471. X    NextArg(XtNbottom, XtChainTop);
  1472. X    NextArg(XtNleft, XtChainLeft);
  1473. X    NextArg(XtNright, XtChainLeft);
  1474. X    NextArg(XtNborderWidth, INTERNAL_BW);
  1475. X
  1476. X    if (strlen(cur_fig_units))
  1477. X    fig_unit_setting = 1;
  1478. X    else {
  1479. X    strcpy(cur_fig_units, appres.INCHES ? "in" : "cm");
  1480. X    }
  1481. X
  1482. X    if (appres.user_scale != 1.0)
  1483. X    fig_scale_setting = 1;
  1484. X
  1485. X    unitbox_sw = XtCreateWidget("unitbox", labelWidgetClass, tool,
  1486. X                Args, ArgCount);
  1487. X    XtAppAddActions(tool_app, unitbox_actions, XtNumber(unitbox_actions));
  1488. X    XtOverrideTranslations(unitbox_sw,
  1489. X               XtParseTranslationTable(unitbox_translations));
  1490. X    return (1);
  1491. X}
  1492. X
  1493. Xstatic String   unit_translations =
  1494. X        "<Message>WM_PROTOCOLS: QuitUnits()\n";
  1495. Xstatic void     unit_panel_cancel(), unit_panel_set();
  1496. Xstatic XtActionsRec     unit_actions[] =
  1497. X{
  1498. X    {"QuitUnits", (XtActionProc) unit_panel_cancel},
  1499. X    {"SetUnit", (XtActionProc) unit_panel_set},
  1500. X};
  1501. X
  1502. Xstatic Widget    unit_popup, form, cancel, set, beside, below, newvalue,
  1503. X        label;
  1504. X
  1505. X/* handle unit/scale settings */
  1506. X
  1507. Xstatic void
  1508. Xunit_panel_dismiss()
  1509. X{
  1510. X    XtDestroyWidget(unit_popup);
  1511. X    XtSetSensitive(unitbox_sw, True);
  1512. X}
  1513. X
  1514. Xstatic void
  1515. Xunit_panel_cancel(w, ev)
  1516. X    Widget        w;
  1517. X    XButtonEvent   *ev;
  1518. X{
  1519. X    unit_panel_dismiss();
  1520. X}
  1521. X
  1522. Xstatic void
  1523. Xunit_panel_set(w, ev)
  1524. X    Widget        w;
  1525. X    XButtonEvent   *ev;
  1526. X{
  1527. X    int old_rul_unit;
  1528. X    char        buf[32];
  1529. X
  1530. X    old_rul_unit = appres.INCHES;
  1531. X    appres.INCHES = rul_unit_setting ? 1 : 0;
  1532. X    init_grid();    /* change point positioning messages if necessary */
  1533. X    if (fig_scale_setting)
  1534. X    appres.user_scale = (float) atof(panel_get_value(scale_factor_panel));
  1535. X    else
  1536. X    appres.user_scale = 1.0;
  1537. X
  1538. X    if (fig_unit_setting) {
  1539. X        strncpy(cur_fig_units,
  1540. X        panel_get_value(user_unit_panel),
  1541. X        sizeof(cur_fig_units));
  1542. X    put_msg("Ruler scale: %s,  Figure scale: 1 %s = %.2f %s",
  1543. X        appres.INCHES ? "in" : "cm",
  1544. X        appres.INCHES ? "in" : "cm",
  1545. X        appres.user_scale, cur_fig_units);
  1546. X    } else {
  1547. X    strcpy(cur_fig_units, appres.INCHES ? "in" : "cm");
  1548. X    put_msg("Ruler scale: %s,  Figure scale = 1:%.2f",
  1549. X        appres.INCHES ? "in" : "cm", appres.user_scale);
  1550. X    }
  1551. X
  1552. X    if (old_rul_unit != appres.INCHES)
  1553. X    reset_rulers();
  1554. X    unit_panel_dismiss();
  1555. X}
  1556. X
  1557. Xstatic void
  1558. Xfig_unit_select(w, new_unit, garbage)
  1559. X    Widget          w;
  1560. X    XtPointer       new_unit, garbage;
  1561. X{
  1562. X    FirstArg(XtNlabel, XtName(w));
  1563. X    SetValues(fig_unit_panel);
  1564. X    fig_unit_setting = (int) new_unit;
  1565. X    XtSetSensitive(user_unit_lab, fig_unit_setting ? True : False);
  1566. X    XtSetSensitive(user_unit_panel, fig_unit_setting ? True : False);
  1567. X    put_msg(fig_unit_setting ? "user defined figure units"
  1568. X                 : "figure units = ruler units");
  1569. X}
  1570. X
  1571. Xstatic void
  1572. Xfig_scale_select(w, new_scale, garbage)
  1573. X    Widget          w;
  1574. X    XtPointer       new_scale, garbage;
  1575. X{
  1576. X    FirstArg(XtNlabel, XtName(w));
  1577. X    SetValues(fig_scale_panel);
  1578. X    fig_scale_setting = (int) new_scale;
  1579. X    XtSetSensitive(scale_factor_lab, fig_scale_setting ? True : False);
  1580. X    XtSetSensitive(scale_factor_panel, fig_scale_setting ? True : False);
  1581. X    put_msg(fig_scale_setting ? "user defined scale factor"
  1582. X                 : "figure scale = 1:1");
  1583. X}
  1584. X
  1585. Xstatic void
  1586. Xrul_unit_select(w, new_unit, garbage)
  1587. X    Widget          w;
  1588. X    XtPointer       new_unit, garbage;
  1589. X{
  1590. X    FirstArg(XtNlabel, XtName(w));
  1591. X    SetValues(rul_unit_panel);
  1592. X    rul_unit_setting = (int) new_unit;
  1593. X    if (rul_unit_setting)
  1594. X    put_msg("ruler scale : centimetres");
  1595. X    else
  1596. X    put_msg("ruler scale : inches");
  1597. X}
  1598. X
  1599. Xvoid
  1600. Xpopup_unit_panel()
  1601. X{
  1602. X    Position        x_val, y_val;
  1603. X    Dimension        width, height;
  1604. X    char        buf[32];
  1605. X    static int      actions_added=0;
  1606. X    static char    *rul_unit_items[] = {
  1607. X    "Metric (cm)  ", "Imperial (in)"};
  1608. X    static char    *fig_unit_items[] = {
  1609. X    "Ruler units ", "User defined"};
  1610. X    static char    *fig_scale_items[] = {
  1611. X    "Unity       ", "User defined"};
  1612. X
  1613. X    FirstArg(XtNwidth, &width);
  1614. X    NextArg(XtNheight, &height);
  1615. X    GetValues(tool);
  1616. X    /* position the popup 2/3 in from left and 1/3 down from top */
  1617. X    XtTranslateCoords(tool, (Position) (2 * width / 3), (Position) (height / 3),
  1618. X              &x_val, &y_val);
  1619. X
  1620. X    FirstArg(XtNx, x_val);
  1621. X    NextArg(XtNy, y_val);
  1622. X    NextArg(XtNwidth, 240);
  1623. X
  1624. X    unit_popup = XtCreatePopupShell("xfig_set_unit_panel",
  1625. X                    transientShellWidgetClass, tool,
  1626. X                    Args, ArgCount);
  1627. X    XtOverrideTranslations(unit_popup,
  1628. X                       XtParseTranslationTable(unit_translations));
  1629. X    if (!actions_added) {
  1630. X        XtAppAddActions(tool_app, unit_actions, XtNumber(unit_actions));
  1631. X    actions_added = 1;
  1632. X    }
  1633. X
  1634. X    form = XtCreateManagedWidget("form", formWidgetClass, unit_popup, NULL, 0);
  1635. X
  1636. X    FirstArg(XtNborderWidth, 0);
  1637. X    sprintf(buf, "      Unit/Scale settings");
  1638. X    label = XtCreateManagedWidget(buf, labelWidgetClass, form, Args, ArgCount);
  1639. X
  1640. X    /* make ruler units menu */
  1641. X
  1642. X    rul_unit_setting = appres.INCHES ? 1 : 0;
  1643. X    FirstArg(XtNfromVert, label);
  1644. X    NextArg(XtNborderWidth, 0);
  1645. X    beside = XtCreateManagedWidget("Ruler Units  =", labelWidgetClass,
  1646. X                                   form, Args, ArgCount);
  1647. X
  1648. X    FirstArg(XtNfromVert, label);
  1649. X    NextArg(XtNfromHoriz, beside);
  1650. X    rul_unit_panel = XtCreateManagedWidget(rul_unit_items[rul_unit_setting],
  1651. X                menuButtonWidgetClass, form, Args, ArgCount);
  1652. X    below = rul_unit_panel;
  1653. X    rul_unit_menu = make_popup_menu(rul_unit_items, XtNumber(rul_unit_items),
  1654. X                                     rul_unit_panel, rul_unit_select);
  1655. X
  1656. X    /* make figure units menu */
  1657. X
  1658. X    FirstArg(XtNfromVert, below);
  1659. X    NextArg(XtNborderWidth, 0);
  1660. X    beside = XtCreateManagedWidget("Figure units =", labelWidgetClass,
  1661. X                                   form, Args, ArgCount);
  1662. X
  1663. X    FirstArg(XtNfromVert, below);
  1664. X    NextArg(XtNfromHoriz, beside);
  1665. X    fig_unit_panel = XtCreateManagedWidget(fig_unit_items[fig_unit_setting],
  1666. X                menuButtonWidgetClass, form, Args, ArgCount);
  1667. X    below = fig_unit_panel;
  1668. X    fig_unit_menu = make_popup_menu(fig_unit_items, XtNumber(fig_unit_items),
  1669. X                                     fig_unit_panel, fig_unit_select);
  1670. X
  1671. X    /* user defined units */
  1672. X
  1673. X    FirstArg(XtNfromVert, below);
  1674. X    NextArg(XtNborderWidth, 0);
  1675. X    NextArg(XtNlabel, "Unit Name =");
  1676. X    user_unit_lab = XtCreateManagedWidget("user_units",
  1677. X                                labelWidgetClass, form, Args, ArgCount);
  1678. X
  1679. X    FirstArg(XtNfromVert, below);
  1680. X    NextArg(XtNborderWidth, INTERNAL_BW);
  1681. X    NextArg(XtNfromHoriz, label);
  1682. X    NextArg(XtNstring, cur_fig_units);
  1683. X    NextArg(XtNinsertPosition, strlen(buf));
  1684. X    NextArg(XtNeditType, "append");
  1685. X    NextArg(XtNwidth, 40);
  1686. X    user_unit_panel = XtCreateManagedWidget(buf, asciiTextWidgetClass,
  1687. X                                    form, Args, ArgCount);
  1688. X    below = user_unit_panel;
  1689. X
  1690. X    /* make figure scale menu */
  1691. X
  1692. X    FirstArg(XtNfromVert, below);
  1693. X    NextArg(XtNborderWidth, 0);
  1694. X    beside = XtCreateManagedWidget("Figure scale =", labelWidgetClass,
  1695. X                                   form, Args, ArgCount);
  1696. X
  1697. X    FirstArg(XtNfromVert, below);
  1698. X    NextArg(XtNfromHoriz, beside);
  1699. X    fig_scale_panel = XtCreateManagedWidget(fig_scale_items[fig_scale_setting],
  1700. X                menuButtonWidgetClass, form, Args, ArgCount);
  1701. X    below = fig_scale_panel;
  1702. X    fig_scale_menu = make_popup_menu(fig_scale_items, XtNumber(fig_scale_items),
  1703. X                                     fig_scale_panel, fig_scale_select);
  1704. X
  1705. X    /* scale factor widget */
  1706. X
  1707. X    FirstArg(XtNfromVert, below);
  1708. X    NextArg(XtNborderWidth, 0);
  1709. X    NextArg(XtNlabel, "Scale factor =");
  1710. X    scale_factor_lab = XtCreateManagedWidget("scale_factor",
  1711. X                                labelWidgetClass, form, Args, ArgCount);
  1712. X
  1713. X    sprintf(buf, "%1.2f", appres.user_scale);
  1714. X    FirstArg(XtNfromVert, below);
  1715. X    NextArg(XtNborderWidth, INTERNAL_BW);
  1716. X    NextArg(XtNfromHoriz, label);
  1717. X    NextArg(XtNstring, buf);
  1718. X    NextArg(XtNinsertPosition, strlen(buf));
  1719. X    NextArg(XtNeditType, "append");
  1720. X    NextArg(XtNwidth, 40);
  1721. X    scale_factor_panel = XtCreateManagedWidget(buf, asciiTextWidgetClass,
  1722. X                                        form, Args, ArgCount);
  1723. X    below = scale_factor_panel;
  1724. X
  1725. X    /* standard cancel/set buttons */
  1726. X
  1727. X    FirstArg(XtNlabel, "cancel");
  1728. X    NextArg(XtNfromVert, below);
  1729. X    NextArg(XtNborderWidth, INTERNAL_BW);
  1730. X    cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
  1731. X                   form, Args, ArgCount);
  1732. X    XtAddEventHandler(cancel, ButtonReleaseMask, (Boolean) 0,
  1733. X              (XtEventHandler)unit_panel_cancel, (XtPointer) NULL);
  1734. X
  1735. X    FirstArg(XtNlabel, "set");
  1736. X    NextArg(XtNfromVert, below);
  1737. X    NextArg(XtNfromHoriz, cancel);
  1738. X    NextArg(XtNborderWidth, INTERNAL_BW);
  1739. X    set = XtCreateManagedWidget("set", commandWidgetClass,
  1740. X                form, Args, ArgCount);
  1741. X    XtAddEventHandler(set, ButtonReleaseMask, (Boolean) 0,
  1742. X              (XtEventHandler)unit_panel_set, (XtPointer) NULL);
  1743. X
  1744. X    XtPopup(unit_popup, XtGrabExclusive);
  1745. X
  1746. X    XtSetSensitive(user_unit_lab, fig_unit_setting ? True : False);
  1747. X    XtSetSensitive(user_unit_panel, fig_unit_setting ? True : False);
  1748. X    XtSetSensitive(scale_factor_lab, fig_scale_setting ? True : False);
  1749. X    XtSetSensitive(scale_factor_panel, fig_scale_setting ? True : False);
  1750. X
  1751. X    (void) XSetWMProtocols(XtDisplay(unit_popup), XtWindow(unit_popup),
  1752. X                           &wm_delete_window, 1);
  1753. X}
  1754. X/************************* TOPRULER ************************/
  1755. X
  1756. XXtActionsRec    topruler_actions[] =
  1757. X{
  1758. X    {"EventTopRuler", (XtActionProc) topruler_selected},
  1759. X    {"ExposeTopRuler", (XtActionProc) topruler_exposed},
  1760. X    {"EnterTopRuler", (XtActionProc) draw_mousefun_topruler},
  1761. X    {"LeaveTopRuler", (XtActionProc) clear_mousefun},
  1762. X};
  1763. X
  1764. Xstatic String    topruler_translations =
  1765. X"Any<BtnDown>:EventTopRuler()\n\
  1766. X    Any<BtnUp>:EventTopRuler()\n\
  1767. X    <Btn2Motion>:EventTopRuler()\n\
  1768. X    Meta <Btn3Motion>:EventTopRuler()\n\
  1769. X    <EnterWindow>:EnterTopRuler()\n\
  1770. X    <LeaveWindow>:LeaveTopRuler()\n\
  1771. X    <Expose>:ExposeTopRuler()\n";
  1772. X
  1773. Xstatic
  1774. Xtopruler_selected(tool, event, params, nparams)
  1775. X    TOOL        tool;
  1776. X    XButtonEvent   *event;
  1777. X    String       *params;
  1778. X    Cardinal       *nparams;
  1779. X{
  1780. X    XButtonEvent   *be = (XButtonEvent *) event;
  1781. X
  1782. X    switch (event->type) {
  1783. X    case ButtonPress:
  1784. X    if (be->button == Button3 && be->state & Mod1Mask) {
  1785. X        be->button = Button2;
  1786. X    }
  1787. X    switch (be->button) {
  1788. X    case Button1:
  1789. X        XDefineCursor(tool_d, topruler_win, l_arrow_cursor);
  1790. X        break;
  1791. X    case Button2:
  1792. X        XDefineCursor(tool_d, topruler_win, bull_cursor);
  1793. X        orig_zoomoff = zoomxoff;
  1794. X        last_drag_x = event->x;
  1795. X        break;
  1796. X    case Button3:
  1797. X        XDefineCursor(tool_d, topruler_win, r_arrow_cursor);
  1798. X        break;
  1799. X    }
  1800. X    break;
  1801. X    case ButtonRelease:
  1802. X    if (be->button == Button3 && be->state & Mod1Mask) {
  1803. X        be->button = Button2;
  1804. X    }
  1805. X    switch (be->button) {
  1806. X    case Button1:
  1807. X        pan_left();
  1808. X        break;
  1809. X    case Button2:
  1810. X        if (orig_zoomoff != zoomxoff)
  1811. X        setup_grid(cur_gridmode);
  1812. X        break;
  1813. X    case Button3:
  1814. X        pan_right();
  1815. X        break;
  1816. X    }
  1817. X    XDefineCursor(tool_d, topruler_win, lr_arrow_cursor);
  1818. X    break;
  1819. X    case MotionNotify:
  1820. X    if (event->x != last_drag_x)
  1821. X        if ((zoomxoff != 0) || (event->x < last_drag_x)) {
  1822. X        zoomxoff -= (event->x - last_drag_x);
  1823. X        if (zoomxoff < 0)
  1824. X            zoomxoff = 0;
  1825. X        reset_topruler();
  1826. X        redisplay_topruler();
  1827. X        }
  1828. X    last_drag_x = event->x;
  1829. X    break;
  1830. X    }
  1831. X}
  1832. X
  1833. Xerase_toprulermark()
  1834. X{
  1835. X    XClearArea(tool_d, topruler_win, ZOOMX(lastx) + troffx,
  1836. X           TOPRULER_HT + troffy, trm_pr.width,
  1837. X           trm_pr.height, False);
  1838. X}
  1839. X
  1840. Xset_toprulermark(x)
  1841. X    int            x;
  1842. X{
  1843. X    XClearArea(tool_d, topruler_win, ZOOMX(lastx) + troffx,
  1844. X           TOPRULER_HT + troffy, trm_pr.width,
  1845. X           trm_pr.height, False);
  1846. X    XCopyArea(tool_d, toparrow_pm, topruler_win, tr_xor_gc,
  1847. X          0, 0, trm_pr.width, trm_pr.height,
  1848. X          ZOOMX(x) + troffx, TOPRULER_HT + troffy);
  1849. X    lastx = x;
  1850. X}
  1851. X
  1852. Xstatic
  1853. Xtopruler_exposed(tool, event, params, nparams)
  1854. X    TOOL        tool;
  1855. X    XButtonEvent   *event;
  1856. X    String       *params;
  1857. X    Cardinal       *nparams;
  1858. X{
  1859. X    if (((XExposeEvent *) event)->count > 0)
  1860. X    return;
  1861. X    redisplay_topruler();
  1862. X}
  1863. X
  1864. Xredisplay_topruler()
  1865. X{
  1866. X    XClearWindow(tool_d, topruler_win);
  1867. X}
  1868. X
  1869. Xint
  1870. Xinit_topruler(tool)
  1871. X    TOOL        tool;
  1872. X{
  1873. X    FirstArg(XtNwidth, TOPRULER_WD);
  1874. X    NextArg(XtNheight, TOPRULER_HT);
  1875. X    NextArg(XtNlabel, "");
  1876. X    NextArg(XtNfromHoriz, mode_panel);
  1877. X    NextArg(XtNhorizDistance, -INTERNAL_BW);
  1878. X    NextArg(XtNfromVert, msg_form);
  1879. X    NextArg(XtNvertDistance, -INTERNAL_BW);
  1880. X    NextArg(XtNresizable, False);
  1881. X    NextArg(XtNtop, XtChainTop);
  1882. X    NextArg(XtNbottom, XtChainTop);
  1883. X    NextArg(XtNleft, XtChainLeft);
  1884. X    NextArg(XtNright, XtChainLeft);
  1885. X    NextArg(XtNborderWidth, INTERNAL_BW);
  1886. X
  1887. X    topruler_sw = XtCreateWidget("topruler", labelWidgetClass, tool,
  1888. X                 Args, ArgCount);
  1889. X
  1890. X    XtAppAddActions(tool_app, topruler_actions, XtNumber(topruler_actions));
  1891. X    XtOverrideTranslations(topruler_sw,
  1892. X               XtParseTranslationTable(topruler_translations));
  1893. X    return (1);
  1894. X}
  1895. X
  1896. Xsetup_topruler()
  1897. X{
  1898. X    unsigned long   bg, fg;
  1899. X    XGCValues        gcv;
  1900. X    unsigned long   gcmask;
  1901. X
  1902. X    topruler_win = XtWindow(topruler_sw);
  1903. X    gcv.font = roman_font->fid;
  1904. X    gcmask = GCFunction | GCForeground | GCBackground | GCFont;
  1905. X
  1906. X    /* set up the GCs */
  1907. X    FirstArg(XtNbackground, &bg);
  1908. X    NextArg(XtNforeground, &fg);
  1909. X    GetValues(topruler_sw);
  1910. X
  1911. X    gcv.foreground = bg;
  1912. X    gcv.background = bg;
  1913. X    gcv.function = GXcopy;
  1914. X    tr_erase_gc = XCreateGC(tool_d, topruler_win, gcmask, &gcv);
  1915. X
  1916. X    gcv.foreground = fg;
  1917. X    tr_gc = XCreateGC(tool_d, topruler_win, gcmask, &gcv);
  1918. X    /*
  1919. X     * The arrows will be XORed into the rulers. We want the foreground color
  1920. X     * in the arrow to result in the foreground or background color in the
  1921. X     * display. so if the source pixel is fg^bg, it produces fg when XOR'ed
  1922. X     * with bg, and bg when XOR'ed with bg. If the source pixel is zero, it
  1923. X     * produces fg when XOR'ed with fg, and bg when XOR'ed with bg.
  1924. X     */
  1925. X    /* first make a temporary xor gc */
  1926. X    gcv.foreground = fg ^ bg;
  1927. X    gcv.background = (unsigned long) 0;
  1928. X    gcv.function = GXcopy;
  1929. X    tr_xor_gc = XCreateGC(tool_d, topruler_win, gcmask, &gcv);
  1930. X
  1931. X    /* make pixmaps for top ruler arrow */
  1932. X    toparrow_pm = XCreatePixmap(tool_d, topruler_win, trm_pr.width,
  1933. X                trm_pr.height, DefaultDepthOfScreen(tool_s));
  1934. X    XPutImage(tool_d, toparrow_pm, tr_xor_gc, &trm_pr, 0, 0, 0, 0,
  1935. X          trm_pr.width, trm_pr.height);
  1936. X    XFreeGC(tool_d, tr_xor_gc);
  1937. X
  1938. X    /* now make the real xor gc */
  1939. X    gcv.background = bg;
  1940. X    gcv.function = GXxor;
  1941. X    tr_xor_gc = XCreateGC(tool_d, topruler_win, gcmask, &gcv);
  1942. X
  1943. X    XDefineCursor(tool_d, topruler_win, lr_arrow_cursor);
  1944. X
  1945. X    topruler_pm = XCreatePixmap(tool_d, topruler_win,
  1946. X                TOPRULER_WD, TOPRULER_HT,
  1947. X                DefaultDepthOfScreen(tool_s));
  1948. X
  1949. X    reset_topruler();
  1950. X}
  1951. X
  1952. Xresize_topruler()
  1953. X{
  1954. X    XFreePixmap(tool_d, topruler_pm);
  1955. X    topruler_pm = XCreatePixmap(tool_d, topruler_win,
  1956. X                TOPRULER_WD, TOPRULER_HT,
  1957. X                DefaultDepthOfScreen(tool_s));
  1958. X
  1959. X    reset_topruler();
  1960. X}
  1961. X
  1962. Xreset_topruler()
  1963. X{
  1964. X    register int    i, j;
  1965. X    register Pixmap p = topruler_pm;
  1966. X    char        number[4];
  1967. X    int            X0;
  1968. X
  1969. X    /* top ruler, adjustments for digits are kludges based on 6x13 char */
  1970. X    XFillRectangle(tool_d, p, tr_erase_gc, 0, 0, TOPRULER_WD, TOPRULER_HT);
  1971. X
  1972. X    X0 = BACKX(0);
  1973. X    if (appres.INCHES) {
  1974. X    X0 -= (X0 % SINCH);
  1975. X    for (i = X0+SINCH-1; i <= X0+round(TOPRULER_WD/zoomscale); i += SINCH) {
  1976. X        j = i + 1;
  1977. X        if (j % PIX_PER_INCH == 0) {
  1978. X        XDrawLine(tool_d, p, tr_gc, ZOOMX(i), TOPRULER_HT - 1, ZOOMX(i),
  1979. X              TOPRULER_HT - INCH_MARK - 1);
  1980. X        sprintf(number, "%d", j / PIX_PER_INCH);
  1981. X        XDrawString(tool_d, p, tr_gc, ZOOMX(i) - 3,
  1982. X                TOPRULER_HT - INCH_MARK - 5, number,
  1983. X                (j < PIX_PER_INCH*10)? 1 : (j<PIX_PER_INCH*100? 2:3));
  1984. X        } else if (j % HINCH == 0)
  1985. X        XDrawLine(tool_d, p, tr_gc, ZOOMX(i), TOPRULER_HT - 1, ZOOMX(i),
  1986. X              TOPRULER_HT - HALF_MARK - 1);
  1987. X        else if (j % QINCH == 0)
  1988. X        XDrawLine(tool_d, p, tr_gc, ZOOMX(i), TOPRULER_HT - 1, ZOOMX(i),
  1989. X              TOPRULER_HT - QUARTER_MARK - 1);
  1990. X        else if (j % SINCH == 0)
  1991. X        XDrawLine(tool_d, p, tr_gc, ZOOMX(i), TOPRULER_HT - 1, ZOOMX(i),
  1992. X              TOPRULER_HT - SIXTEENTH_MARK - 1);
  1993. X    }
  1994. X    } else {
  1995. X    X0 -= (X0 % TWOMM);
  1996. X    for (i = X0+TWOMM-1; i <= X0+round(TOPRULER_WD/zoomscale); i++) {
  1997. X        j = i + 1;
  1998. X        if (j % PIX_PER_CM == 0) {
  1999. X        XDrawLine(tool_d, p, tr_gc, ZOOMX(i), TOPRULER_HT - 1, ZOOMX(i),
  2000. X              TOPRULER_HT - INCH_MARK - 1);
  2001. X        sprintf(number, "%d", j / PIX_PER_CM);
  2002. X        XDrawString(tool_d, p, tr_gc, ZOOMX(i) - 3,
  2003. X                TOPRULER_HT - INCH_MARK - 5, number,
  2004. X                (j < PIX_PER_CM*10)? 1 : (j<PIX_PER_CM*100? 2:3));
  2005. X        } else if (j % TWOMM == 0)
  2006. X        XDrawLine(tool_d, p, tr_gc, ZOOMX(i), TOPRULER_HT - 1, ZOOMX(i),
  2007. X              TOPRULER_HT - QUARTER_MARK - 1);
  2008. X    }
  2009. X    }
  2010. X    /* change the pixmap ID to fool the intrinsics to actually set the pixmap */
  2011. X    FirstArg(XtNbackgroundPixmap, 0);
  2012. X    SetValues(topruler_sw);
  2013. X    FirstArg(XtNbackgroundPixmap, p);
  2014. X    SetValues(topruler_sw);
  2015. X}
  2016. X
  2017. X/************************* SIDERULER ************************/
  2018. X
  2019. XXtActionsRec    sideruler_actions[] =
  2020. X{
  2021. X    {"EventSideRuler", (XtActionProc) sideruler_selected},
  2022. X    {"ExposeSideRuler", (XtActionProc) sideruler_exposed},
  2023. X    {"EnterSideRuler", (XtActionProc) draw_mousefun_sideruler},
  2024. X    {"LeaveSideRuler", (XtActionProc) clear_mousefun},
  2025. X};
  2026. X
  2027. Xstatic String    sideruler_translations =
  2028. X"Any<BtnDown>:EventSideRuler()\n\
  2029. X    Any<BtnUp>:EventSideRuler()\n\
  2030. X    <Btn2Motion>:EventSideRuler()\n\
  2031. X    Meta <Btn3Motion>:EventSideRuler()\n\
  2032. X    <EnterWindow>:EnterSideRuler()\n\
  2033. X    <LeaveWindow>:LeaveSideRuler()\n\
  2034. X    <Expose>:ExposeSideRuler()\n";
  2035. X
  2036. Xstatic
  2037. Xsideruler_selected(tool, event, params, nparams)
  2038. X    TOOL        tool;
  2039. X    XButtonEvent   *event;
  2040. X    String       *params;
  2041. X    Cardinal       *nparams;
  2042. X{
  2043. X    XButtonEvent   *be = (XButtonEvent *) event;
  2044. X
  2045. X    switch (event->type) {
  2046. X    case ButtonPress:
  2047. X    if (be->button == Button3 && be->state & Mod1Mask) {
  2048. X        be->button = Button2;
  2049. X    }
  2050. X    switch (be->button) {
  2051. X    case Button1:
  2052. X        XDefineCursor(tool_d, sideruler_win, u_arrow_cursor);
  2053. X        break;
  2054. X    case Button2:
  2055. X        XDefineCursor(tool_d, sideruler_win, bull_cursor);
  2056. X        orig_zoomoff = zoomyoff;
  2057. X        last_drag_y = event->y;
  2058. X        break;
  2059. X    case Button3:
  2060. X        XDefineCursor(tool_d, sideruler_win, d_arrow_cursor);
  2061. X        break;
  2062. X    }
  2063. X    break;
  2064. X    case ButtonRelease:
  2065. X    if (be->button == Button3 && be->state & Mod1Mask) {
  2066. X        be->button = Button2;
  2067. X    }
  2068. X    switch (be->button) {
  2069. X    case Button1:
  2070. X        pan_up();
  2071. X        break;
  2072. X    case Button2:
  2073. X        if (orig_zoomoff != zoomyoff)
  2074. X        setup_grid(cur_gridmode);
  2075. X        break;
  2076. X    case Button3:
  2077. X        pan_down();
  2078. X        break;
  2079. X    }
  2080. X    XDefineCursor(tool_d, sideruler_win, ud_arrow_cursor);
  2081. X    break;
  2082. X    case MotionNotify:
  2083. X    if (event->y != last_drag_y)
  2084. X        if ((zoomyoff != 0) || (event->y < last_drag_y)) {
  2085. X        zoomyoff -= (event->y - last_drag_y);
  2086. X        if (zoomyoff < 0)
  2087. X            zoomyoff = 0;
  2088. X        reset_sideruler();
  2089. X        redisplay_sideruler();
  2090. X        }
  2091. X    last_drag_y = event->y;
  2092. X    break;
  2093. X    }
  2094. X}
  2095. X
  2096. Xstatic
  2097. Xsideruler_exposed(tool, event, params, nparams)
  2098. X    TOOL        tool;
  2099. X    XButtonEvent   *event;
  2100. X    String       *params;
  2101. X    Cardinal       *nparams;
  2102. X{
  2103. X    if (((XExposeEvent *) event)->count > 0)
  2104. X    return;
  2105. X    redisplay_sideruler();
  2106. X}
  2107. X
  2108. Xint
  2109. Xinit_sideruler(tool)
  2110. X    TOOL        tool;
  2111. X{
  2112. X    FirstArg(XtNwidth, SIDERULER_WD);
  2113. X    NextArg(XtNheight, SIDERULER_HT);
  2114. X    NextArg(XtNlabel, "");
  2115. X    NextArg(XtNfromHoriz, canvas_sw);
  2116. X    NextArg(XtNhorizDistance, -INTERNAL_BW);
  2117. X    NextArg(XtNfromVert, topruler_sw);
  2118. X    NextArg(XtNvertDistance, -INTERNAL_BW);
  2119. X    NextArg(XtNresizable, False);
  2120. X    NextArg(XtNtop, XtChainTop);
  2121. X    NextArg(XtNbottom, XtChainTop);
  2122. X    NextArg(XtNleft, XtChainLeft);
  2123. X    NextArg(XtNright, XtChainLeft);
  2124. X    NextArg(XtNborderWidth, INTERNAL_BW);
  2125. X
  2126. X    sideruler_sw = XtCreateWidget("sideruler", labelWidgetClass, tool,
  2127. X                  Args, ArgCount);
  2128. X
  2129. X    XtAppAddActions(tool_app, sideruler_actions, XtNumber(sideruler_actions));
  2130. X    XtOverrideTranslations(sideruler_sw,
  2131. X               XtParseTranslationTable(sideruler_translations));
  2132. X    return (1);
  2133. X}
  2134. X
  2135. Xredisplay_sideruler()
  2136. X{
  2137. X    XClearWindow(tool_d, sideruler_win);
  2138. X}
  2139. X
  2140. Xsetup_sideruler()
  2141. X{
  2142. X    unsigned long   bg, fg;
  2143. X    XGCValues        gcv;
  2144. X    unsigned long   gcmask;
  2145. X
  2146. X    sideruler_win = XtWindow(sideruler_sw);
  2147. X    gcv.font = roman_font->fid;
  2148. X    gcmask = GCFunction | GCForeground | GCBackground | GCFont;
  2149. X
  2150. X    /* set up the GCs */
  2151. X    FirstArg(XtNbackground, &bg);
  2152. X    NextArg(XtNforeground, &fg);
  2153. X    GetValues(sideruler_sw);
  2154. X
  2155. X    gcv.foreground = bg;
  2156. X    gcv.background = bg;
  2157. X    gcv.function = GXcopy;
  2158. X    sr_erase_gc = XCreateGC(tool_d, sideruler_win, gcmask, &gcv);
  2159. X
  2160. X    gcv.foreground = fg;
  2161. X    sr_gc = XCreateGC(tool_d, sideruler_win, gcmask, &gcv);
  2162. X    /*
  2163. X     * The arrows will be XORed into the rulers. We want the foreground color
  2164. X     * in the arrow to result in the foreground or background color in the
  2165. X     * display. so if the source pixel is fg^bg, it produces fg when XOR'ed
  2166. X     * with bg, and bg when XOR'ed with bg. If the source pixel is zero, it
  2167. X     * produces fg when XOR'ed with fg, and bg when XOR'ed with bg.
  2168. X     */
  2169. X    /* first make a temporary xor gc */
  2170. X    gcv.foreground = fg ^ bg;
  2171. X    gcv.background = (unsigned long) 0;
  2172. X    gcv.function = GXcopy;
  2173. X    sr_xor_gc = XCreateGC(tool_d, sideruler_win, gcmask, &gcv);
  2174. X
  2175. X    /* make pixmaps for side ruler arrow */
  2176. X    if (appres.RHS_PANEL) {
  2177. X    sidearrow_pm = XCreatePixmap(tool_d, sideruler_win,
  2178. X                     srlm_pr.width, srlm_pr.height,
  2179. X                     DefaultDepthOfScreen(tool_s));
  2180. X    XPutImage(tool_d, sidearrow_pm, sr_xor_gc, &srlm_pr, 0, 0, 0, 0,
  2181. X          srlm_pr.width, srlm_pr.height);
  2182. X    } else {
  2183. X    sidearrow_pm = XCreatePixmap(tool_d, sideruler_win,
  2184. X                     srrm_pr.width, srrm_pr.height,
  2185. X                     DefaultDepthOfScreen(tool_s));
  2186. X    XPutImage(tool_d, sidearrow_pm, sr_xor_gc, &srrm_pr, 0, 0, 0, 0,
  2187. X          srrm_pr.width, srrm_pr.height);
  2188. X    }
  2189. X    XFreeGC(tool_d, sr_xor_gc);
  2190. X
  2191. X    /* now make the real xor gc */
  2192. X    gcv.background = bg;
  2193. X    gcv.function = GXxor;
  2194. X    sr_xor_gc = XCreateGC(tool_d, sideruler_win, gcmask, &gcv);
  2195. X
  2196. X    XDefineCursor(tool_d, sideruler_win, ud_arrow_cursor);
  2197. X
  2198. X    sideruler_pm = XCreatePixmap(tool_d, sideruler_win,
  2199. X                 SIDERULER_WD, SIDERULER_HT,
  2200. X                 DefaultDepthOfScreen(tool_s));
  2201. X
  2202. X    reset_sideruler();
  2203. X}
  2204. X
  2205. Xresize_sideruler()
  2206. X{
  2207. X    XFreePixmap(tool_d, sideruler_pm);
  2208. X    sideruler_pm = XCreatePixmap(tool_d, sideruler_win,
  2209. X                 SIDERULER_WD, SIDERULER_HT,
  2210. X                 DefaultDepthOfScreen(tool_s));
  2211. X    reset_sideruler();
  2212. X}
  2213. X
  2214. Xreset_sideruler()
  2215. X{
  2216. X    register int    i, j;
  2217. X    register Pixmap p = sideruler_pm;
  2218. X    char        number[4];
  2219. X    int            Y0;
  2220. X
  2221. X    /* side ruler, adjustments for digits are kludges based on 6x13 char */
  2222. X    XFillRectangle(tool_d, p, sr_erase_gc, 0, 0, SIDERULER_WD,
  2223. X           (int) (SIDERULER_HT));
  2224. X
  2225. X    Y0 = BACKY(0);
  2226. X    if (appres.INCHES) {
  2227. X    Y0 -= (Y0 % SINCH);
  2228. X    if (appres.RHS_PANEL) {
  2229. X        for (i = Y0+SINCH-1; i <= Y0+round(SIDERULER_HT/zoomscale); i += SINCH) {
  2230. X        j = i + 1;
  2231. X        if (j % PIX_PER_INCH == 0) {
  2232. X            XDrawLine(tool_d, p, sr_gc, SIDERULER_WD - INCH_MARK,
  2233. X                  ZOOMY(i), SIDERULER_WD, ZOOMY(i));
  2234. X            sprintf(number, "%3d", j / PIX_PER_INCH);
  2235. X            XDrawString(tool_d, p, sr_gc,
  2236. X                SIDERULER_WD - INCH_MARK - 22, ZOOMY(i) + 3,
  2237. X                number, 3);
  2238. X        } else if (j % HINCH == 0)
  2239. X            XDrawLine(tool_d, p, sr_gc,
  2240. X                  SIDERULER_WD - HALF_MARK, ZOOMY(i),
  2241. X                  SIDERULER_WD, ZOOMY(i));
  2242. X        else if (j % QINCH == 0)
  2243. X            XDrawLine(tool_d, p, sr_gc,
  2244. X                  SIDERULER_WD - QUARTER_MARK, ZOOMY(i),
  2245. X                  SIDERULER_WD, ZOOMY(i));
  2246. X        else if (j % SINCH == 0)
  2247. X            XDrawLine(tool_d, p, sr_gc,
  2248. X                  SIDERULER_WD - SIXTEENTH_MARK, ZOOMY(i),
  2249. X                  SIDERULER_WD, ZOOMY(i));
  2250. X        }
  2251. X    } else {
  2252. X        for (i = Y0+SINCH-1; i <= Y0+round(SIDERULER_HT/zoomscale); i += SINCH) {
  2253. X        j = i + 1;
  2254. X        if (j % PIX_PER_INCH == 0) {
  2255. X            XDrawLine(tool_d, p, sr_gc, 0, ZOOMY(i),
  2256. X                  INCH_MARK - 1, ZOOMY(i));
  2257. X            sprintf(number, "%3d", j / PIX_PER_INCH);
  2258. X            XDrawString(tool_d, p, sr_gc, INCH_MARK + 3,
  2259. X                ZOOMY(i) + 3, number, 3);
  2260. X        } else if (j % HINCH == 0)
  2261. X            XDrawLine(tool_d, p, sr_gc, 0, ZOOMY(i),
  2262. X                  HALF_MARK - 1, ZOOMY(i));
  2263. X        else if (j % QINCH == 0)
  2264. X            XDrawLine(tool_d, p, sr_gc, 0, ZOOMY(i),
  2265. X                  QUARTER_MARK - 1, ZOOMY(i));
  2266. X        else if (j % SINCH == 0)
  2267. X            XDrawLine(tool_d, p, sr_gc, 0, ZOOMY(i),
  2268. X                  SIXTEENTH_MARK - 1, ZOOMY(i));
  2269. X        }
  2270. X    }
  2271. X    } else {
  2272. X    Y0 -= (Y0 % TWOMM);
  2273. X    if (appres.RHS_PANEL) {
  2274. X        for (i = Y0+TWOMM-1; i <= Y0+round(SIDERULER_HT/zoomscale); i++) {
  2275. X        j = i + 1;
  2276. X        if (j % PIX_PER_CM == 0) {
  2277. X            XDrawLine(tool_d, p, sr_gc, SIDERULER_WD - INCH_MARK,
  2278. X                  ZOOMY(i), SIDERULER_WD, ZOOMY(i));
  2279. X            sprintf(number, "%3d", j / PIX_PER_CM);
  2280. X            XDrawString(tool_d, p, sr_gc,
  2281. X                SIDERULER_WD - INCH_MARK - 14, ZOOMY(i) + 3,
  2282. X                number, 3);
  2283. X        } else if (j % TWOMM == 0)
  2284. X            XDrawLine(tool_d, p, sr_gc,
  2285. X                  SIDERULER_WD - QUARTER_MARK, ZOOMY(i),
  2286. X                  SIDERULER_WD, ZOOMY(i));
  2287. X        }
  2288. X    } else {
  2289. X        for (i = Y0+TWOMM-1; i <= Y0+round(SIDERULER_HT/zoomscale); i++) {
  2290. X        j = i + 1;
  2291. X        if (j % PIX_PER_CM == 0) {
  2292. X            XDrawLine(tool_d, p, sr_gc, 0, ZOOMY(i),
  2293. X                  INCH_MARK - 1, ZOOMY(i));
  2294. X            sprintf(number, "%3d", j / PIX_PER_CM);
  2295. X            XDrawString(tool_d, p, sr_gc, INCH_MARK + 3,
  2296. X                ZOOMY(i) + 3, number, 3);
  2297. X        } else if (j % TWOMM == 0)
  2298. X            XDrawLine(tool_d, p, sr_gc, 0, ZOOMY(i),
  2299. X                  QUARTER_MARK - 1, ZOOMY(i));
  2300. X        }
  2301. X    }
  2302. X    }
  2303. X    /* change the pixmap ID to fool the intrinsics to actually set the pixmap */
  2304. X    FirstArg(XtNbackgroundPixmap, 0);
  2305. X    SetValues(sideruler_sw);
  2306. X    FirstArg(XtNbackgroundPixmap, p);
  2307. X    SetValues(sideruler_sw);
  2308. X}
  2309. X
  2310. Xerase_siderulermark()
  2311. X{
  2312. X    if (appres.RHS_PANEL)
  2313. X    XClearArea(tool_d, sideruler_win,
  2314. X           SIDERULER_WD + srloffx, ZOOMY(lasty) + srloffy,
  2315. X           srlm_pr.width, srlm_pr.height, False);
  2316. X    else
  2317. X    XClearArea(tool_d, sideruler_win,
  2318. X           srroffx, ZOOMY(lasty) + srroffy,
  2319. X           srlm_pr.width, srlm_pr.height, False);
  2320. X}
  2321. X
  2322. Xset_siderulermark(y)
  2323. X    int            y;
  2324. X{
  2325. X    if (appres.RHS_PANEL) {
  2326. X    /*
  2327. X     * Because the ruler uses a background pixmap, we can win here by
  2328. X     * using XClearArea to erase the old thing.
  2329. X     */
  2330. X    XClearArea(tool_d, sideruler_win,
  2331. X           SIDERULER_WD + srloffx, ZOOMY(lasty) + srloffy,
  2332. X           srlm_pr.width, srlm_pr.height, False);
  2333. X    XCopyArea(tool_d, sidearrow_pm, sideruler_win,
  2334. X          sr_xor_gc, 0, 0, srlm_pr.width,
  2335. X          srlm_pr.height, SIDERULER_WD + srloffx, ZOOMY(y) + srloffy);
  2336. X    } else {
  2337. X    /*
  2338. X     * Because the ruler uses a background pixmap, we can win here by
  2339. X     * using XClearArea to erase the old thing.
  2340. X     */
  2341. X    XClearArea(tool_d, sideruler_win,
  2342. X           srroffx, ZOOMY(lasty) + srroffy,
  2343. X           srlm_pr.width, srlm_pr.height, False);
  2344. X    XCopyArea(tool_d, sidearrow_pm, sideruler_win,
  2345. X          sr_xor_gc, 0, 0, srrm_pr.width,
  2346. X          srrm_pr.height, srroffx, ZOOMY(y) + srroffy);
  2347. X    }
  2348. X    lasty = y;
  2349. X}
  2350. END_OF_FILE
  2351. if test 31896 -ne `wc -c <'w_rulers.c'`; then
  2352.     echo shar: \"'w_rulers.c'\" unpacked with wrong size!
  2353. fi
  2354. # end of 'w_rulers.c'
  2355. fi
  2356. echo shar: End of archive 18 \(of 27\).
  2357. cp /dev/null ark18isdone
  2358. MISSING=""
  2359. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ; do
  2360.     if test ! -f ark${I}isdone ; then
  2361.     MISSING="${MISSING} ${I}"
  2362.     fi
  2363. done
  2364. if test "${MISSING}" = "" ; then
  2365.     echo You have unpacked all 27 archives.
  2366.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2367. else
  2368.     echo You still need to unpack the following archives:
  2369.     echo "        " ${MISSING}
  2370. fi
  2371. ##  End of shell archive.
  2372. exit 0
  2373.  
  2374. exit 0 # Just in case...
  2375. -- 
  2376.   // chris@IMD.Sterling.COM       | Send comp.sources.x submissions to:
  2377. \X/  Amiga - The only way to fly! |    sources-x@imd.sterling.com
  2378.  "It's intuitively obvious to the |
  2379.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  2380.