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

  1. Newsgroups: comp.sources.x
  2. From: envbvs@epb9.lbl.gov (Brian V. Smith)
  3. Subject: v19i126:  xfig - Draw amd manipulate objects in an X-Window, Part14/27
  4. Message-ID: <1993May21.021542.6381@sparky.imd.sterling.com>
  5. X-Md4-Signature: 6b939c97ebf71c341a1318a8ccb213e8
  6. Sender: chris@sparky.imd.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Fri, 21 May 1993 02:15:42 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 126
  13. Archive-name: xfig/part14
  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 14 (of 27)."
  24. # Contents:  d_text.c u_elastic.c w_rottext.c
  25. # Wrapped by envbvs@epb9.lbl.gov.lbl.gov on Mon May  3 12:05:57 1993
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'd_text.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'d_text.c'\"
  29. else
  30. echo shar: Extracting \"'d_text.c'\" \(21193 characters\)
  31. sed "s/^X//" >'d_text.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) 1992 by Brian V. Smith
  36. X * "Permission to use, copy, modify, distribute, and sell this software and its
  37. X * documentation for any purpose is hereby granted without fee, provided that
  38. X * the above copyright notice appear in all copies and that both the copyright
  39. X * notice and this permission notice appear in supporting documentation. 
  40. X * No representations are made about the suitability of this software for 
  41. X * any purpose.  It is provided "as is" without express or implied warranty."
  42. X */
  43. X
  44. X#include "fig.h"
  45. X#include "resources.h"
  46. X#include "mode.h"
  47. X#include "object.h"
  48. X#include "paintop.h"
  49. X#include "u_create.h"
  50. X#include "u_fonts.h"
  51. X#include "u_list.h"
  52. X#include "u_search.h"
  53. X#include "w_canvas.h"
  54. X#include "w_drawprim.h"
  55. X#include "w_mousefun.h"
  56. X#include "w_setup.h"
  57. X#include "w_zoom.h"
  58. X
  59. Xextern PIX_ROT_FONT lookfont();
  60. X
  61. X#define CTRL_H    8
  62. X#define NL    10
  63. X#define CR    13
  64. X#define CTRL_X    24
  65. X#define SP    32
  66. X#define DEL    127
  67. X
  68. X#define            BUF_SIZE    400
  69. X
  70. Xchar        prefix[BUF_SIZE],    /* part of string left of mouse click */
  71. X        suffix[BUF_SIZE];    /* part to right of click */
  72. Xint        leng_prefix, leng_suffix;
  73. Xstatic int    char_ht;
  74. Xstatic int    base_x, base_y;
  75. Xstatic PIX_ROT_FONT canvas_zoomed_font;
  76. X
  77. Xstatic int    work_psflag, work_font, work_fontsize, work_textjust;
  78. Xstatic PIX_ROT_FONT work_fontstruct;
  79. Xstatic float    work_angle;
  80. Xstatic        finish_n_start();
  81. Xstatic        init_text_input(), cancel_text_input();
  82. Xstatic        wrap_up();
  83. Xint        char_handler();
  84. Xstatic F_text  *new_text();
  85. X
  86. Xstatic int    cpy_n_char();
  87. Xstatic int    prefix_length();
  88. Xstatic int    initialize_char_handler();
  89. Xstatic int    terminate_char_handler();
  90. Xstatic int    erase_char_string();
  91. Xstatic int    draw_char_string();
  92. Xstatic int    turn_on_blinking_cursor();
  93. Xstatic int    turn_off_blinking_cursor();
  94. Xstatic int    move_blinking_cursor();
  95. X
  96. Xtext_drawing_selected()
  97. X{
  98. X    canvas_kbd_proc = null_proc;
  99. X    canvas_locmove_proc = null_proc;
  100. X    canvas_middlebut_proc = null_proc;
  101. X    canvas_leftbut_proc = init_text_input;
  102. X    canvas_rightbut_proc = null_proc;
  103. X    set_mousefun("posn cursor", "", "");
  104. X    set_cursor(pencil_cursor);
  105. X}
  106. X
  107. Xstatic
  108. Xfinish_n_start(x, y)
  109. X{
  110. X    wrap_up();
  111. X    init_text_input(x, y);
  112. X}
  113. X
  114. Xfinish_text_input()
  115. X{
  116. X    wrap_up();
  117. X    text_drawing_selected();
  118. X    draw_mousefun_canvas();
  119. X}
  120. X
  121. Xstatic
  122. Xcancel_text_input()
  123. X{
  124. X    erase_char_string();
  125. X    terminate_char_handler();
  126. X    if (cur_t != NULL) {
  127. X    draw_text(cur_t, PAINT);
  128. X    toggle_textmarker(cur_t);
  129. X    }
  130. X    text_drawing_selected();
  131. X    draw_mousefun_canvas();
  132. X    reset_action_on();
  133. X}
  134. X
  135. Xstatic
  136. Xnew_text_line()
  137. X{
  138. X    wrap_up();
  139. X    if (work_angle < 90.0 - 0.001) {
  140. X    cur_y += (int) ((float) char_ht * cur_textstep);
  141. X    cur_x = base_x;
  142. X    } else if (work_angle < 180.0 - 0.001) {
  143. X    cur_x += (int) ((float) char_ht * cur_textstep);
  144. X    cur_y = base_y;
  145. X    } else if (work_angle < 270.0 - 0.001) {
  146. X    cur_y -= (int) ((float) char_ht * cur_textstep);
  147. X    cur_x = base_x;
  148. X    } else {
  149. X    cur_x -= (int) ((float) char_ht * cur_textstep);
  150. X    cur_y = base_y;
  151. X    }
  152. X    init_text_input(cur_x, cur_y);
  153. X}
  154. X
  155. Xstatic
  156. Xwrap_up()
  157. X{
  158. X    PR_SIZE        size;
  159. X
  160. X    reset_action_on();
  161. X    erase_char_string();
  162. X    terminate_char_handler();
  163. X
  164. X    if (cur_t == NULL) {    /* a brand new text */
  165. X    if (leng_prefix == 0)
  166. X        return;
  167. X    cur_t = new_text();
  168. X    add_text(cur_t);
  169. X    } else {            /* existing text modified */
  170. X    strcat(prefix, suffix);
  171. X    leng_prefix += leng_suffix;
  172. X    if (leng_prefix == 0) {
  173. X        delete_text(cur_t);
  174. X        return;
  175. X    }
  176. X    if (!strcmp(cur_t->cstring, prefix)) {
  177. X        /* we didn't change anything */
  178. X        draw_text(cur_t, PAINT);
  179. X        toggle_textmarker(cur_t);
  180. X        return;
  181. X    }
  182. X    new_t = copy_text(cur_t);
  183. X    change_text(cur_t, new_t);
  184. X    if (strlen(new_t->cstring) >= leng_prefix) {
  185. X        strcpy(new_t->cstring, prefix);
  186. X    } else {        /* free old and allocate new */
  187. X        free(new_t->cstring);
  188. X        if ((new_t->cstring = new_string(leng_prefix + 1)) != NULL)
  189. X        strcpy(new_t->cstring, prefix);
  190. X    }
  191. X    size = pf_textwidth(canvas_font, leng_prefix, prefix);
  192. X    new_t->height = size.y;
  193. X    new_t->length = size.x; /* in pixels */
  194. X    cur_t = new_t;
  195. X    }
  196. X    draw_text(cur_t, PAINT);
  197. X    mask_toggle_textmarker(cur_t);
  198. X}
  199. X
  200. Xstatic
  201. Xinit_text_input(x, y)
  202. X    int            x, y;
  203. X{
  204. X    int            length, d;
  205. X    PR_SIZE        tsize;
  206. X
  207. X    cur_x = x;
  208. X    cur_y = y;
  209. X
  210. X    set_action_on();
  211. X    set_mousefun("reposn cursor", "finish text", "cancel");
  212. X    draw_mousefun_canvas();
  213. X    canvas_kbd_proc = char_handler;
  214. X    canvas_middlebut_proc = finish_text_input;
  215. X    canvas_leftbut_proc = finish_n_start;
  216. X    canvas_rightbut_proc = cancel_text_input;
  217. X
  218. X    /*
  219. X     * set working font info to current settings. This allows user to change
  220. X     * font settings while we are in the middle of accepting text without
  221. X     * affecting this text i.e. we don't allow the text to change midway
  222. X     * through
  223. X     */
  224. X
  225. X    put_msg("Ready for text input (from keyboard)");
  226. X    if ((cur_t = text_search(cur_x, cur_y)) == NULL) {    /* new text input */
  227. X    leng_prefix = leng_suffix = 0;
  228. X    *suffix = 0;
  229. X    prefix[leng_prefix] = '\0';
  230. X    base_x = cur_x;
  231. X    base_y = cur_y;
  232. X
  233. X    work_fontsize = cur_fontsize;
  234. X    work_font     = using_ps ? cur_ps_font : cur_latex_font;
  235. X    work_psflag   = using_ps;
  236. X    work_textjust = cur_textjust;
  237. X    work_angle    = cur_elltextangle;
  238. X    if (work_angle < 0.0)
  239. X        work_angle += 360.0;
  240. X
  241. X    /* load the X font and get its id for this font, size and angle UNZOOMED */
  242. X    /* this is to get widths etc for the unzoomed chars */
  243. X    canvas_font = lookfont(x_fontnum(work_psflag, work_font), 
  244. X               work_fontsize, work_angle*M_PI/180.0);
  245. X    /* get the ZOOMED font for actually drawing on the canvas */
  246. X    canvas_zoomed_font = lookfont(x_fontnum(work_psflag, work_font), 
  247. X               round(work_fontsize*zoomscale), work_angle*M_PI/180.0);
  248. X    /* save the working font structure */
  249. X    work_fontstruct = canvas_zoomed_font;
  250. X    } else {            /* clicked on existing text */
  251. X    if (hidden_text(cur_t)) {
  252. X        put_msg("Can't edit hidden text");
  253. X        reset_action_on();
  254. X        text_drawing_selected();
  255. X        return;
  256. X    }
  257. X    /* update the working text parameters */
  258. X    work_font = cur_t->font;
  259. X    work_fontstruct = canvas_zoomed_font = cur_t->fontstruct;
  260. X    work_fontsize = cur_t->size;
  261. X    work_psflag   = cur_t->flags;
  262. X    work_textjust = cur_t->type;
  263. X    work_angle    = cur_t->angle*180.0/M_PI;
  264. X    if (work_angle < 0.0)
  265. X        work_angle += 360.0;
  266. X    /* load the X font and get its id for this font, size and angle UNZOOMED */
  267. X    /* this is to get widths etc for the unzoomed chars */
  268. X    canvas_font = lookfont(x_fontnum(work_psflag, work_font), 
  269. X               work_fontsize, work_angle*M_PI/180.0);
  270. X
  271. X    toggle_textmarker(cur_t);
  272. X    draw_text(cur_t, ERASE);
  273. X    base_x = cur_t->base_x;
  274. X    base_y = cur_t->base_y;
  275. X    length = cur_t->length;
  276. X    switch (cur_t->type) {
  277. X    case T_CENTER_JUSTIFIED:
  278. X        if (work_angle < 90.0 - 0.001) 
  279. X        base_x -= length / 2;
  280. X        else if (work_angle < 180.0 - 0.001)
  281. X        base_y += length / 2;
  282. X        else if (work_angle < 270.0 - 0.001)
  283. X        base_x += length / 2;
  284. X        else
  285. X        base_y -= length / 2;
  286. X        break;
  287. X
  288. X    case T_RIGHT_JUSTIFIED:
  289. X        if (work_angle < 90.0 - 0.001) 
  290. X        base_x -= length;
  291. X        else if (work_angle < 180.0 - 0.001)
  292. X        base_y += length;
  293. X        else if (work_angle < 270.0 - 0.001)
  294. X        base_x += length;
  295. X        else
  296. X        base_y -= length;
  297. X        break;
  298. X    } /* switch */
  299. X    if (work_angle < 90.0 - 0.001 || (work_angle >= 180.0 - 0.001 
  300. X        && work_angle < 270.0 - 0.001))
  301. X        d = abs(cur_x - base_x);
  302. X    else
  303. X        d = abs(cur_y - base_y);
  304. X    leng_suffix = strlen(cur_t->cstring);
  305. X    /* leng_prefix is # of char in the text before the cursor */
  306. X    leng_prefix = prefix_length(cur_t->cstring, d);
  307. X    leng_suffix -= leng_prefix;
  308. X    cpy_n_char(prefix, cur_t->cstring, leng_prefix);
  309. X    strcpy(suffix, &cur_t->cstring[leng_prefix]);
  310. X    tsize = pf_textwidth(canvas_font, leng_prefix, prefix);
  311. X
  312. X    if (work_angle < 90.0 - 0.001) {
  313. X        cur_x = base_x + tsize.x;
  314. X        cur_y = base_y;
  315. X    } else if (work_angle < 180.0 - 0.001) {
  316. X        cur_x = base_x;
  317. X        cur_y = base_y - tsize.x;
  318. X    } else if (work_angle < 270.0 - 0.001) {
  319. X        cur_x = base_x - tsize.x;
  320. X        cur_y = base_y;
  321. X    } else {
  322. X        cur_x = base_x;
  323. X        cur_y = base_y + tsize.x;
  324. X    }
  325. X    }
  326. X    char_ht = rot_char_height(canvas_font);
  327. X    initialize_char_handler(canvas_win, finish_text_input,
  328. X                base_x, base_y);
  329. X    draw_char_string();
  330. X}
  331. X
  332. Xstatic
  333. XF_text           *
  334. Xnew_text()
  335. X{
  336. X    F_text       *text;
  337. X    PR_SIZE        size;
  338. X
  339. X    if ((text = create_text()) == NULL)
  340. X    return (NULL);
  341. X
  342. X    if ((text->cstring = new_string(leng_prefix + 1)) == NULL) {
  343. X    free((char *) text);
  344. X    return (NULL);
  345. X    }
  346. X    text->type = work_textjust;
  347. X    text->font = work_font;    /* put in current font number */
  348. X    text->fontstruct = work_fontstruct;
  349. X    text->size = work_fontsize;
  350. X    text->angle = work_angle/180.0*M_PI;    /* convert to radians */
  351. X    text->flags = cur_textflags;
  352. X    text->color = cur_color;
  353. X    text->depth = cur_depth;
  354. X    text->pen = 0;
  355. X    size = pf_textwidth(canvas_font, leng_prefix, prefix);
  356. X    text->length = size.x;    /* in pixels */
  357. X    text->height = size.y;    /* in pixels */
  358. X    text->base_x = base_x;
  359. X    text->base_y = base_y;
  360. X    strcpy(text->cstring, prefix);
  361. X    text->next = NULL;
  362. X    return (text);
  363. X}
  364. X
  365. Xstatic int
  366. Xcpy_n_char(dst, src, n)
  367. X    char       *dst, *src;
  368. X    int            n;
  369. X{
  370. X    /* src must be longer than n chars */
  371. X
  372. X    while (n--)
  373. X    *dst++ = *src++;
  374. X    *dst = '\0';
  375. X}
  376. X
  377. Xstatic int
  378. Xprefix_length(string, where_p)
  379. X    char       *string;
  380. X    int            where_p;
  381. X{
  382. X    /* c stands for character unit and p for pixel unit */
  383. X    int            l, len_c, len_p;
  384. X    int            char_wid, where_c;
  385. X    PR_SIZE        size;
  386. X
  387. X    len_c = strlen(string);
  388. X    size = pf_textwidth(canvas_font, len_c, string);
  389. X    len_p = size.x;
  390. X    if (where_p >= len_p)
  391. X    return (len_c);        /* entire string is the prefix */
  392. X
  393. X    char_wid = rot_char_width(canvas_font);
  394. X    where_c = where_p / char_wid;    /* estimated char position */
  395. X    size = pf_textwidth(canvas_font, where_c, string);
  396. X    l = size.x;            /* actual length (pixels) of string of
  397. X                 * where_c chars */
  398. X    if (l < where_p) {
  399. X    do {            /* add the width of next char to l */
  400. X        l += (char_wid = rot_char_advance(canvas_font, 
  401. X                (unsigned char) string[where_c++]));
  402. X    } while (l < where_p);
  403. X    if (l - (char_wid >> 1) >= where_p)
  404. X        where_c--;
  405. X    } else if (l > where_p) {
  406. X    do {            /* subtract the width of last char from l */
  407. X        l -= (char_wid = rot_char_advance(canvas_font, 
  408. X                (unsigned char) string[--where_c]));
  409. X    } while (l > where_p);
  410. X    if (l + (char_wid >> 1) >= where_p)
  411. X        where_c++;
  412. X    }
  413. X    if (where_c < 0) {
  414. X    fprintf(stderr, "xfig file %s line %d: Error in prefix_length - adjusted\n", __FILE__, __LINE__);
  415. X    where_c = 0;
  416. X    }
  417. X    return (where_c);
  418. X}
  419. X
  420. X/*******************************************************************
  421. X
  422. X    char handling routines
  423. X
  424. X*******************************************************************/
  425. X
  426. X#define            BLINK_INTERVAL    700    /* milliseconds blink rate */
  427. X
  428. Xstatic Window    pw;
  429. Xstatic int    ch_height;
  430. Xstatic int    cbase_x, cbase_y;
  431. Xstatic float    rbase_x, rbase_y, rcur_x, rcur_y;
  432. X
  433. Xstatic        (*cr_proc) ();
  434. X
  435. Xstatic
  436. Xdraw_cursor(x, y)
  437. X    int            x, y;
  438. X{
  439. X    if (work_angle < 90.0 - 0.001)        /* 0-89 degrees */
  440. X        pw_vector(pw, x, y, x, y-ch_height, INV_PAINT, 1, RUBBER_LINE, 0.0,
  441. X        DEFAULT_COLOR);
  442. X    else if (work_angle < 180.0 - 0.001)    /* 90-179 degrees */
  443. X        pw_vector(pw, x-ch_height, y, x, y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  444. X        DEFAULT_COLOR);
  445. X    else if (work_angle < 270.0 - 0.001)    /* 180-269 degrees */
  446. X        pw_vector(pw, x, y+ch_height, x, y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  447. X        DEFAULT_COLOR);
  448. X    else                /* 270-359 degrees */
  449. X        pw_vector(pw, x, y, x+ch_height, y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  450. X        DEFAULT_COLOR);
  451. X}
  452. X
  453. Xstatic int
  454. Xinitialize_char_handler(p, cr, bx, by)
  455. X    Window        p;
  456. X    int            (*cr) ();
  457. X    int            bx, by;
  458. X{
  459. X    pw = p;
  460. X    cr_proc = cr;
  461. X    rbase_x = cbase_x = bx;    /* keep real base so dont have roundoff */
  462. X    rbase_y = cbase_y = by;
  463. X    rcur_x = cur_x;
  464. X    rcur_y = cur_y;
  465. X
  466. X    ch_height = rot_char_height(canvas_font);
  467. X    turn_on_blinking_cursor(draw_cursor, draw_cursor,
  468. X                cur_x, cur_y, (long) BLINK_INTERVAL);
  469. X}
  470. X
  471. Xstatic int
  472. Xterminate_char_handler()
  473. X{
  474. X    turn_off_blinking_cursor();
  475. X    cr_proc = NULL;
  476. X}
  477. X
  478. X/*
  479. X * we use INV_PAINT below instead of ERASE and PAINT to avoid interactions
  480. X * with the cursor.  It means that we need to do a ERASE before we start the
  481. X * cursor and a PAINT after it is turned off.
  482. X */
  483. X
  484. Xstatic int
  485. Xerase_char_string()
  486. X{
  487. X    pw_text(pw, cbase_x, cbase_y, INV_PAINT, canvas_zoomed_font, 
  488. X        prefix, DEFAULT_COLOR);
  489. X    if (leng_suffix)
  490. X    pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  491. X        suffix, DEFAULT_COLOR);
  492. X}
  493. X
  494. Xstatic int
  495. Xdraw_char_string()
  496. X{
  497. X    pw_text(pw, cbase_x, cbase_y, INV_PAINT, canvas_zoomed_font, 
  498. X        prefix, DEFAULT_COLOR);
  499. X    if (leng_suffix)
  500. X    pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  501. X        suffix, DEFAULT_COLOR);
  502. X    move_blinking_cursor(cur_x, cur_y);
  503. X}
  504. X
  505. Xstatic int
  506. Xdraw_suffix()
  507. X{
  508. X    if (leng_suffix)
  509. X    pw_text(pw, cur_x, cur_y, PAINT, canvas_zoomed_font, 
  510. X        suffix, DEFAULT_COLOR);
  511. X}
  512. X
  513. Xstatic int
  514. Xerase_suffix()
  515. X{
  516. X    if (leng_suffix)
  517. X    pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  518. X        suffix, DEFAULT_COLOR);
  519. X}
  520. X
  521. Xstatic int
  522. Xdraw_char(c)
  523. Xchar    c;
  524. X{
  525. X    char    s[2];
  526. X    s[0]=c;
  527. X    s[1]='\0';
  528. X    pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  529. X        s, DEFAULT_COLOR);
  530. X}
  531. X
  532. Xchar_handler(c)
  533. X    unsigned char   c;
  534. X{
  535. X    float        cwidth, cw2;
  536. X
  537. X    if (cr_proc == NULL)
  538. X    return;
  539. X
  540. X    if (c == CR || c == NL) {
  541. X    new_text_line();
  542. X    } else if (c == DEL || c == CTRL_H) {
  543. X    if (leng_prefix > 0) {
  544. X        erase_char_string();
  545. X        cwidth = (float) rot_char_advance(canvas_font, 
  546. X            (unsigned char) prefix[leng_prefix - 1]);
  547. X        cw2 = cwidth/2.0;
  548. X        /* correct text/cursor posn for justification and zoom factor */
  549. X        switch (work_textjust) {
  550. X        case T_LEFT_JUSTIFIED:
  551. X        if (work_angle < 90.0 - 0.001)
  552. X            rcur_x -= cwidth;           /* 0-89 deg, move the suffix left */
  553. X        else if (work_angle < 180.0 - 0.001) 
  554. X            rcur_y += cwidth;           /* 90-179 deg, move suffix down */
  555. X        else if (work_angle < 270.0 - 0.001) 
  556. X            rcur_x += cwidth;           /* 180-269 deg, move suffix right */
  557. X        else 
  558. X            rcur_y -= cwidth;           /* 270-359 deg, move suffix up */
  559. X        break;
  560. X        case T_CENTER_JUSTIFIED:
  561. X        if (work_angle < 90.0 - 0.001) { 
  562. X            rbase_x += cw2;    /* 0-89 deg, move base right cw/2 */
  563. X            rcur_x -= cw2;    /* move suffix left by cw/2 */
  564. X        } else if (work_angle < 180.0 - 0.001) { 
  565. X            rbase_y -= cw2;    /* 90-179 deg, move base up cw/2 */
  566. X            rcur_y += cw2;    /* move suffix down cw/2 */
  567. X        } else if (work_angle < 270.0 - 0.001) {
  568. X            rbase_x -= cw2;    /* 180-269 deg, move base left cw/2 */
  569. X            rcur_x += cw2;    /* move suffix right cw/2 */
  570. X        } else {                      
  571. X            rbase_y += cw2;    /* 270-359 deg, move base down cw/2 */
  572. X            rcur_y -= cw2;    /* move suffix up cw/2 */
  573. X        }
  574. X        break;
  575. X        case T_RIGHT_JUSTIFIED:
  576. X        if (work_angle < 90.0 - 0.001) 
  577. X            rbase_x += cwidth;           /* 0-89 deg, move the prefix right */
  578. X        else if (work_angle < 180.0 - 0.001)
  579. X            rbase_y -= cwidth;           /* 90-179 deg, move prefix up */
  580. X        else if (work_angle < 270.0 - 0.001)
  581. X            rbase_x -= cwidth;           /* 180-269 deg, move prefix left */
  582. X        else
  583. X            rbase_y += cwidth;           /* 270-359 deg, move prefix down */
  584. X        break;
  585. X        }
  586. X        prefix[--leng_prefix] = '\0';
  587. X        cbase_x = rbase_x;    /* fix */
  588. X        cbase_y = rbase_y;
  589. X        cur_x = rcur_x;
  590. X        cur_y = rcur_y;
  591. X        draw_char_string();
  592. X    }
  593. X    } else if (c == CTRL_X) {
  594. X    if (leng_prefix > 0) {
  595. X        erase_char_string();
  596. X        switch (work_textjust) {
  597. X        case T_CENTER_JUSTIFIED:
  598. X        while (leng_prefix--)    /* subtract char width/2 per char */
  599. X            if (work_angle < 90.0 - 0.001)    /* 0-89 degrees */
  600. X            rcur_x -= rot_char_advance(canvas_font, 
  601. X                (unsigned char) prefix[leng_prefix]) / 2.0;
  602. X        else if (work_angle < 180.0 - 0.001)     /* 90-179 degrees */
  603. X            rcur_y += rot_char_advance(canvas_font, 
  604. X                (unsigned char) prefix[leng_prefix]) / 2.0;
  605. X        else if (work_angle < 270.0 - 0.001)     /* 180-269 degrees */
  606. X            rcur_x += rot_char_advance(canvas_font, 
  607. X                (unsigned char) prefix[leng_prefix]) / 2.0;
  608. X        else                     /* 270-359 degrees */
  609. X            rcur_y -= rot_char_advance(canvas_font, 
  610. X                (unsigned char) prefix[leng_prefix]) / 2.0;
  611. X        cur_x = cbase_x = rbase_x = rcur_x;
  612. X        cur_y = cbase_y = rbase_y = rcur_y;
  613. X        break;
  614. X        case T_RIGHT_JUSTIFIED:
  615. X        cbase_x = rbase_x = cur_x = rcur_x;
  616. X        cbase_y = rbase_y = cur_y = rcur_y;
  617. X        break;
  618. X        case T_LEFT_JUSTIFIED:
  619. X        cur_x = rcur_x = cbase_x = rbase_x;
  620. X        cur_y = rcur_y = cbase_y = rbase_y;
  621. X        break;
  622. X        }
  623. X        leng_prefix = 0;
  624. X        *prefix = '\0';
  625. X        draw_char_string();
  626. X    }
  627. X    } else if (c < SP) {
  628. X    put_msg("Invalid character ignored");
  629. X    } else if (leng_prefix + leng_suffix == BUF_SIZE) {
  630. X    put_msg("Text buffer is full, character is ignored");
  631. X
  632. X    /* normal text character */
  633. X    } else {    
  634. X    draw_char_string();
  635. X    cwidth = rot_char_advance(canvas_font, (unsigned char) c);
  636. X    cw2 = cwidth/2.0;
  637. X    /* correct text/cursor posn for justification and zoom factor */
  638. X    switch (work_textjust) {
  639. X      case T_LEFT_JUSTIFIED:
  640. X        if (work_angle < 90.0 - 0.001)
  641. X        rcur_x += cwidth;           /* 0-89 deg, move the suffix right */
  642. X        else if (work_angle < 180.0 - 0.001) 
  643. X        rcur_y -= cwidth;           /* 90-179 deg, move suffix up */
  644. X        else if (work_angle < 270.0 - 0.001) 
  645. X        rcur_x -= cwidth;           /* 180-269 deg, move suffix left */
  646. X        else 
  647. X        rcur_y += cwidth;           /* 270-359 deg, move suffix down */
  648. X        break;
  649. X      case T_CENTER_JUSTIFIED:
  650. X        if (work_angle < 90.0 - 0.001) { 
  651. X        rbase_x -= cw2;    /* 0-89 deg, move base left cw/2 */
  652. X        rcur_x += cw2;    /* move suffix right by cw/2 */
  653. X        } else if (work_angle < 180.0 - 0.001) { 
  654. X        rbase_y += cw2;    /* 90-179 deg, move base down cw/2 */
  655. X        rcur_y -= cw2;    /* move suffix up cw/2 */
  656. X        } else if (work_angle < 270.0 - 0.001) {
  657. X        rbase_x += cw2;    /* 180-269 deg, move base right cw/2 */
  658. X        rcur_x -= cw2;    /* move suffix left cw/2 */
  659. X        } else {                      
  660. X        rbase_y -= cw2;    /* 270-359 deg, move base up cw/2 */
  661. X        rcur_y += cw2;    /* move suffix down cw/2 */
  662. X        }
  663. X        break;
  664. X      case T_RIGHT_JUSTIFIED:
  665. X        if (work_angle < 90.0 - 0.001) 
  666. X        rbase_x -= cwidth;           /* 0-89 deg, move the prefix left */
  667. X        else if (work_angle < 180.0 - 0.001)
  668. X        rbase_y += cwidth;           /* 90-179 deg, move prefix down */
  669. X        else if (work_angle < 270.0 - 0.001)
  670. X        rbase_x += cwidth;           /* 180-269 deg, move prefix right */
  671. X        else
  672. X        rbase_y -= cwidth;           /* 270-359 deg, move prefix up */
  673. X        break;
  674. X    }
  675. X    prefix[leng_prefix++] = c;
  676. X    prefix[leng_prefix] = '\0';
  677. X    cbase_x = rbase_x;
  678. X    cbase_y = rbase_y;
  679. X    cur_x = rcur_x;
  680. X    cur_y = rcur_y;
  681. X    draw_char_string();
  682. X    }
  683. X}
  684. X
  685. X/*******************************************************************
  686. X
  687. X    blinking cursor handling routines
  688. X
  689. X*******************************************************************/
  690. X
  691. Xstatic int    cursor_on, cursor_is_moving;
  692. Xstatic int    cursor_x, cursor_y;
  693. Xstatic int    (*erase) ();
  694. Xstatic int    (*draw) ();
  695. Xstatic XtTimerCallbackProc blink();
  696. Xstatic unsigned long blink_timer;
  697. Xstatic XtIntervalId blinkid;
  698. Xstatic int    stop_blinking = False;
  699. Xstatic int    cur_is_blinking = False;
  700. X
  701. Xstatic int
  702. Xturn_on_blinking_cursor(draw_cursor, erase_cursor, x, y, msec)
  703. X    int            (*draw_cursor) ();
  704. X    int            (*erase_cursor) ();
  705. X    int            x, y;
  706. X    unsigned long   msec;
  707. X{
  708. X    draw = draw_cursor;
  709. X    erase = erase_cursor;
  710. X    cursor_is_moving = 0;
  711. X    cursor_x = x;
  712. X    cursor_y = y;
  713. X    blink_timer = msec;
  714. X    draw(x, y);
  715. X    cursor_on = 1;
  716. X    if (!cur_is_blinking) {    /* if we are already blinking, don't request
  717. X                 * another */
  718. X    blinkid = XtAppAddTimeOut(tool_app, blink_timer, (XtTimerCallbackProc) blink,
  719. X                  (XtPointer) NULL);
  720. X    cur_is_blinking = True;
  721. X    }
  722. X    stop_blinking = False;
  723. X}
  724. X
  725. Xstatic int
  726. Xturn_off_blinking_cursor()
  727. X{
  728. X    if (cursor_on)
  729. X    erase(cursor_x, cursor_y);
  730. X    stop_blinking = True;
  731. X}
  732. X
  733. Xstatic        XtTimerCallbackProc
  734. Xblink(client_data, id)
  735. X    XtPointer        client_data;
  736. X    XtIntervalId   *id;
  737. X{
  738. X    if (!stop_blinking) {
  739. X    if (cursor_is_moving)
  740. X        return (0);
  741. X    if (cursor_on) {
  742. X        erase(cursor_x, cursor_y);
  743. X        cursor_on = 0;
  744. X    } else {
  745. X        draw(cursor_x, cursor_y);
  746. X        cursor_on = 1;
  747. X    }
  748. X    blinkid = XtAppAddTimeOut(tool_app, blink_timer, (XtTimerCallbackProc) blink,
  749. X                  (XtPointer) NULL);
  750. X    } else {
  751. X    stop_blinking = False;    /* signal that we've stopped */
  752. X    cur_is_blinking = False;
  753. X    }
  754. X    return (0);
  755. X}
  756. X
  757. Xstatic int
  758. Xmove_blinking_cursor(x, y)
  759. X    int            x, y;
  760. X{
  761. X    cursor_is_moving = 1;
  762. X    if (cursor_on)
  763. X    erase(cursor_x, cursor_y);
  764. X    cursor_x = x;
  765. X    cursor_y = y;
  766. X    draw(cursor_x, cursor_y);
  767. X    cursor_on = 1;
  768. X    cursor_is_moving = 0;
  769. X}
  770. X
  771. Xreload_text_fstructs()
  772. X{
  773. X    F_text       *t;
  774. X
  775. X    /* reload the compound objects' texts */
  776. X    reload_compoundfont(objects.compounds);
  777. X    /* and the separate texts */
  778. X    for (t=objects.texts; t != NULL; t = t->next)
  779. X    reload_text_fstruct(t);
  780. X}
  781. X
  782. X/*
  783. X * Reload the font structure for texts in compounds.
  784. X */
  785. X
  786. Xreload_compoundfont(compounds)
  787. X    F_compound       *compounds;
  788. X{
  789. X    F_compound       *c;
  790. X    F_text       *t;
  791. X
  792. X    for (c = compounds; c != NULL; c = c->next) {
  793. X    reload_compoundfont(c->compounds);
  794. X    for (t=c->texts; t != NULL; t = t->next)
  795. X        reload_text_fstruct(t);
  796. X    }
  797. X}
  798. X
  799. Xreload_text_fstruct(t)
  800. X    F_text       *t;
  801. X{
  802. X    t->fontstruct = lookfont(x_fontnum(t->flags, t->font), 
  803. X            round(t->size*zoomscale), t->angle);
  804. X}
  805. END_OF_FILE
  806. if test 21193 -ne `wc -c <'d_text.c'`; then
  807.     echo shar: \"'d_text.c'\" unpacked with wrong size!
  808. fi
  809. # end of 'd_text.c'
  810. fi
  811. if test -f 'u_elastic.c' -a "${1}" != "-c" ; then 
  812.   echo shar: Will not clobber existing file \"'u_elastic.c'\"
  813. else
  814. echo shar: Extracting \"'u_elastic.c'\" \(20435 characters\)
  815. sed "s/^X//" >'u_elastic.c' <<'END_OF_FILE'
  816. X/*
  817. X * FIG : Facility for Interactive Generation of figures
  818. X * Copyright (c) 1985 by Supoj Sutanthavibul
  819. X *
  820. X * "Permission to use, copy, modify, distribute, and sell this software and its
  821. X * documentation for any purpose is hereby granted without fee, provided that
  822. X * the above copyright notice appear in all copies and that both the copyright
  823. X * notice and this permission notice appear in supporting documentation. 
  824. X * No representations are made about the suitability of this software for 
  825. X * any purpose.  It is provided "as is" without express or implied warranty."
  826. X */
  827. X
  828. X#include "fig.h"
  829. X#include "resources.h"
  830. X#include "mode.h"
  831. X#include "object.h"
  832. X#include "paintop.h"
  833. X#include "u_elastic.h"
  834. X#include "w_canvas.h"
  835. X#include "w_setup.h"
  836. X#include "w_zoom.h"
  837. X
  838. Xextern float    compute_angle();
  839. X
  840. X/********************** EXPORTS **************/
  841. X
  842. Xint        constrained;
  843. Xint        fix_x, fix_y, work_numsides;
  844. Xfloat        cur_angle;
  845. Xint        x1off, x2off, y1off, y2off;
  846. XCursor        cur_latexcursor;
  847. Xint        from_x, from_y;
  848. Xdouble        cosa, sina;
  849. Xint        movedpoint_num;
  850. XF_point           *left_point, *right_point;
  851. X
  852. X/**************** LOCAL ***********/
  853. X
  854. Xstatic void    elastic_links();
  855. X
  856. X/*************************** BOXES *************************/
  857. X
  858. Xelastic_box(x1, y1, x2, y2)
  859. X    int            x1, y1, x2, y2;
  860. X{
  861. X    /* line_style = RUBBER_LINE so that we don't scale it */
  862. X    pw_vector(canvas_win, x1, y1, x1, y2, INV_PAINT, 1, RUBBER_LINE, 0.0,
  863. X          DEFAULT_COLOR);
  864. X    pw_vector(canvas_win, x1, y2, x2, y2, INV_PAINT, 1, RUBBER_LINE, 0.0,
  865. X          DEFAULT_COLOR);
  866. X    pw_vector(canvas_win, x2, y2, x2, y1, INV_PAINT, 1, RUBBER_LINE, 0.0,
  867. X          DEFAULT_COLOR);
  868. X    pw_vector(canvas_win, x2, y1, x1, y1, INV_PAINT, 1, RUBBER_LINE, 0.0,
  869. X          DEFAULT_COLOR);
  870. X}
  871. X
  872. Xelastic_movebox()
  873. X{
  874. X    register int    x1, y1, x2, y2;
  875. X
  876. X    x1 = cur_x + x1off;
  877. X    x2 = cur_x + x2off;
  878. X    y1 = cur_y + y1off;
  879. X    y2 = cur_y + y2off;
  880. X    elastic_box(x1, y1, x2, y2);
  881. X    elastic_links(cur_x - fix_x, cur_y - fix_y, 1.0, 1.0);
  882. X}
  883. X
  884. Xmoving_box(x, y)
  885. X    int            x, y;
  886. X{
  887. X    elastic_movebox();
  888. X    adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  889. X    elastic_movebox();
  890. X}
  891. X
  892. Xresizing_box(x, y)
  893. X    int            x, y;
  894. X{
  895. X    elastic_box(fix_x, fix_y, cur_x, cur_y);
  896. X    cur_x = x;
  897. X    cur_y = y;
  898. X    elastic_box(fix_x, fix_y, cur_x, cur_y);
  899. X    boxsize_msg();
  900. X}
  901. X
  902. Xconstrained_resizing_box(x, y)
  903. X    int            x, y;
  904. X{
  905. X    elastic_box(fix_x, fix_y, cur_x, cur_y);
  906. X    adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  907. X    elastic_box(fix_x, fix_y, cur_x, cur_y);
  908. X    boxsize_msg();
  909. X}
  910. X
  911. Xscaling_compound(x, y)
  912. X    int            x, y;
  913. X{
  914. X    elastic_scalecompound(cur_c);
  915. X    adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  916. X    elastic_scalecompound(cur_c);
  917. X}
  918. X
  919. Xelastic_scalecompound(c)
  920. X    F_compound       *c;
  921. X{
  922. X    int            newx, newy, oldx, oldy, x1, y1, x2, y2;
  923. X    float        newd, oldd, scalefact;
  924. X
  925. X    newx = cur_x - fix_x;
  926. X    newy = cur_y - fix_y;
  927. X    newd = sqrt((double) (newx * newx + newy * newy));
  928. X    oldx = from_x - fix_x;
  929. X    oldy = from_y - fix_y;
  930. X    oldd = sqrt((double) (oldx * oldx + oldy * oldy));
  931. X    scalefact = newd / oldd;
  932. X    x1 = fix_x + (c->secorner.x - fix_x) * scalefact;
  933. X    y1 = fix_y + (c->secorner.y - fix_y) * scalefact;
  934. X    x2 = fix_x + (c->nwcorner.x - fix_x) * scalefact;
  935. X    y2 = fix_y + (c->nwcorner.y - fix_y) * scalefact;
  936. X    elastic_box(x1, y1, x2, y2);
  937. X}
  938. X
  939. X/*************************** LINES *************************/
  940. X
  941. Xelastic_line()
  942. X{
  943. X    pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y,
  944. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  945. X}
  946. X
  947. Xfreehand_line(x, y)
  948. X    int            x, y;
  949. X{
  950. X    elastic_line();
  951. X    cur_x = x;
  952. X    cur_y = y;
  953. X    elastic_line();
  954. X    length_msg(MSG_LENGTH);
  955. X}
  956. X
  957. Xlatex_line(x, y)
  958. X    int            x, y;
  959. X{
  960. X    Cursor c;
  961. X
  962. X    elastic_line();
  963. X    latex_endpoint(fix_x, fix_y, x, y, &cur_x, &cur_y, latexarrow_mode,
  964. X           (cur_pointposn == P_ANY) ? 1 : posn_rnd[cur_pointposn]);
  965. X    elastic_line();
  966. X    length_msg(MSG_LENGTH);
  967. X    c = (x == cur_x && y == cur_y) ? null_cursor : crosshair_cursor;
  968. X    if (c != cur_cursor) {
  969. X    set_temp_cursor(c);
  970. X    cur_cursor = c;
  971. X    }
  972. X}
  973. X
  974. Xconstrainedangle_line(x, y)
  975. X    int            x, y;
  976. X{
  977. X    float        angle, dx, dy;
  978. X
  979. X    if (x == cur_x && y == cur_y)
  980. X    return;
  981. X
  982. X    dx = x - fix_x;
  983. X    dy = fix_y - y;
  984. X    if (sqrt((double) (dx * dx + dy * dy)) < 7)
  985. X    return;
  986. X    if (dx == 0)
  987. X    angle = -90;
  988. X    else
  989. X    angle = 180 * atan((double) (dy / dx)) / 3.1416;
  990. X
  991. X    elastic_line();
  992. X    if (manhattan_mode) {
  993. X    if (mountain_mode) {
  994. X        if (angle < -67.5)
  995. X        angle90_line(x, y);
  996. X        else if (angle < -22.5)
  997. X        angle135_line(x, y);
  998. X        else if (angle < 22.5)
  999. X        angle0_line(x, y);
  1000. X        else if (angle < 67.5)
  1001. X        angle45_line(x, y);
  1002. X        else
  1003. X        angle90_line(x, y);
  1004. X    } else {
  1005. X        if (angle < -45)
  1006. X        angle90_line(x, y);
  1007. X        else if (angle < 45)
  1008. X        angle0_line(x, y);
  1009. X        else
  1010. X        angle90_line(x, y);
  1011. X    }
  1012. X    } else {
  1013. X    if (angle < 0)
  1014. X        angle135_line(x, y);
  1015. X    else
  1016. X        angle45_line(x, y);
  1017. X    }
  1018. X    elastic_line();
  1019. X    length_msg(MSG_LENGTH);
  1020. X}
  1021. X
  1022. Xangle0_line(x, y)
  1023. X    int            x, y;
  1024. X{
  1025. X    cur_x = x;
  1026. X    cur_y = fix_y;
  1027. X}
  1028. X
  1029. Xangle90_line(x, y)
  1030. X    int            x, y;
  1031. X{
  1032. X    cur_y = y;
  1033. X    cur_x = fix_x;
  1034. X}
  1035. X
  1036. Xangle45_line(x, y)
  1037. X    int            x, y;
  1038. X{
  1039. X    if (abs(x - fix_x) < abs(y - fix_y)) {
  1040. X    cur_x = fix_x - y + fix_y;
  1041. X    cur_y = y;
  1042. X    } else {
  1043. X    cur_y = fix_y + fix_x - x;
  1044. X    cur_x = x;
  1045. X    }
  1046. X}
  1047. X
  1048. Xangle135_line(x, y)
  1049. X    int            x, y;
  1050. X{
  1051. X    if (abs(x - fix_x) < abs(y - fix_y)) {
  1052. X    cur_x = fix_x + y - fix_y;
  1053. X    cur_y = y;
  1054. X    } else {
  1055. X    cur_y = fix_y + x - fix_x;
  1056. X    cur_x = x;
  1057. X    }
  1058. X}
  1059. X
  1060. Xreshaping_line(x, y)
  1061. X    int            x, y;
  1062. X{
  1063. X    elastic_linelink();
  1064. X    adjust_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  1065. X    elastic_linelink();
  1066. X    /* one or two lines moving with the move point? */
  1067. X    if (left_point != NULL && right_point != NULL) {
  1068. X    length_msg2(left_point->x,left_point->y,
  1069. X            right_point->x,right_point->y,cur_x,cur_y);
  1070. X    } else if (left_point != NULL) {
  1071. X    altlength_msg(MSG_LENGTH,left_point->x,left_point->y);
  1072. X    } else if (right_point != NULL) {
  1073. X    altlength_msg(MSG_LENGTH,right_point->x,right_point->y);
  1074. X    }
  1075. X}
  1076. X
  1077. Xelastic_linelink()
  1078. X{
  1079. X    if (left_point != NULL) {
  1080. X    pw_vector(canvas_win, left_point->x, left_point->y,
  1081. X           cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1082. X    }
  1083. X    if (right_point != NULL) {
  1084. X    pw_vector(canvas_win, right_point->x, right_point->y,
  1085. X           cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1086. X    }
  1087. X}
  1088. X
  1089. Xmoving_line(x, y)
  1090. X    int            x, y;
  1091. X{
  1092. X    elastic_moveline(new_l->points);
  1093. X    adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1094. X    elastic_moveline(new_l->points);
  1095. X}
  1096. X
  1097. Xelastic_moveline(pts)
  1098. X    F_point       *pts;
  1099. X{
  1100. X    F_point       *p;
  1101. X    int            dx, dy, x, y, xx, yy;
  1102. X
  1103. X    p = pts;
  1104. X    if (p->next == NULL) {    /* dot */
  1105. X    pw_vector(canvas_win, cur_x, cur_y, cur_x, cur_y,
  1106. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1107. X    } else {
  1108. X    dx = cur_x - fix_x;
  1109. X    dy = cur_y - fix_y;
  1110. X    x = p->x + dx;
  1111. X    y = p->y + dy;
  1112. X    for (p = p->next; p != NULL; x = xx, y = yy, p = p->next) {
  1113. X        xx = p->x + dx;
  1114. X        yy = p->y + dy;
  1115. X        pw_vector(canvas_win, x, y, xx, yy, INV_PAINT, 1,
  1116. X              RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1117. X    }
  1118. X    }
  1119. X    elastic_links(dx, dy, 1.0, 1.0);
  1120. X}
  1121. X
  1122. Xstatic void
  1123. Xelastic_links(dx, dy, sx, sy)
  1124. X    int            dx, dy;
  1125. X    float        sx, sy;
  1126. X{
  1127. X    F_linkinfo       *k;
  1128. X
  1129. X    if (cur_linkmode == SMART_OFF)
  1130. X    return;
  1131. X
  1132. X    for (k = cur_links; k != NULL; k = k->next)
  1133. X    if (k->prevpt == NULL) {/* dot */
  1134. X        pw_vector(canvas_win, k->endpt->x, k->endpt->y,
  1135. X              k->endpt->x, k->endpt->y,
  1136. X              INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1137. X    } else {
  1138. X        if (cur_linkmode == SMART_MOVE)
  1139. X        pw_vector(canvas_win, k->endpt->x + dx, k->endpt->y + dy,
  1140. X              k->prevpt->x, k->prevpt->y,
  1141. X              INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1142. X        else if (cur_linkmode == SMART_SLIDE) {
  1143. X        if (k->endpt->x == k->prevpt->x) {
  1144. X            if (!k->two_pts)
  1145. X            pw_vector(canvas_win, k->prevpt->x,
  1146. X                  k->prevpt->y, k->prevpt->x + dx, k->prevpt->y,
  1147. X                 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1148. X            pw_vector(canvas_win, k->endpt->x + dx,
  1149. X              k->endpt->y + dy, k->prevpt->x + dx, k->prevpt->y,
  1150. X                  INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1151. X        } else {
  1152. X            if (!k->two_pts)
  1153. X            pw_vector(canvas_win, k->prevpt->x,
  1154. X                  k->prevpt->y, k->prevpt->x, k->prevpt->y + dy,
  1155. X                 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1156. X            pw_vector(canvas_win, k->endpt->x + dx,
  1157. X              k->endpt->y + dy, k->prevpt->x, k->prevpt->y + dy,
  1158. X                  INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1159. X        }
  1160. X        }
  1161. X    }
  1162. X}
  1163. X
  1164. Xscaling_line(x, y)
  1165. X    int            x, y;
  1166. X{
  1167. X    elastic_scalepts(cur_l->points);
  1168. X    adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1169. X    elastic_scalepts(cur_l->points);
  1170. X    /* could add check for box here and do a boxsize_msg */
  1171. X}
  1172. X
  1173. Xscaling_spline(x, y)
  1174. X    int            x, y;
  1175. X{
  1176. X    elastic_scalepts(cur_s->points);
  1177. X    adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1178. X    elastic_scalepts(cur_s->points);
  1179. X}
  1180. X
  1181. Xelastic_scalepts(pts)
  1182. X    F_point       *pts;
  1183. X{
  1184. X    F_point       *p;
  1185. X    int            newx, newy, oldx, oldy, ox, oy, xx, yy;
  1186. X    float        newd, oldd, scalefact;
  1187. X
  1188. X    p = pts;
  1189. X    newx = cur_x - fix_x;
  1190. X    newy = cur_y - fix_y;
  1191. X    newd = sqrt((double) (newx * newx + newy * newy));
  1192. X
  1193. X    oldx = from_x - fix_x;
  1194. X    oldy = from_y - fix_y;
  1195. X    oldd = sqrt((double) (oldx * oldx + oldy * oldy));
  1196. X
  1197. X    scalefact = newd / oldd;
  1198. X    ox = fix_x + (p->x - fix_x) * scalefact;
  1199. X    oy = fix_y + (p->y - fix_y) * scalefact;
  1200. X    for (p = p->next; p != NULL; ox = xx, oy = yy, p = p->next) {
  1201. X    xx = fix_x + (p->x - fix_x) * scalefact;
  1202. X    yy = fix_y + (p->y - fix_y) * scalefact;
  1203. X    pw_vector(canvas_win, ox, oy, xx, yy, INV_PAINT, 1,
  1204. X          RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1205. X    }
  1206. X}
  1207. X
  1208. Xelastic_poly(x1, y1, x2, y2, numsides)
  1209. X    int            x1, y1, x2, y2, numsides;
  1210. X{
  1211. X    register float  angle;
  1212. X    register int    nx, ny, dx, dy, i;
  1213. X    float        init_angle, mag;
  1214. X    int            ox, oy;
  1215. X
  1216. X    dx = x2 - x1;
  1217. X    dy = y2 - y1;
  1218. X    mag = sqrt((double) (dx * dx + dy * dy));
  1219. X    init_angle = compute_angle((float) dx, (float) dy);
  1220. X    ox = x2;
  1221. X    oy = y2;
  1222. X
  1223. X    /* now append numsides points */
  1224. X    for (i = 1; i < numsides; i++) {
  1225. X    angle = init_angle - M_2PI * (float) i / (float) numsides;
  1226. X    if (angle < 0)
  1227. X        angle += M_2PI;
  1228. X    nx = x1 + round(mag * cos((double) angle));
  1229. X    ny = y1 + round(mag * sin((double) angle));
  1230. X    pw_vector(canvas_win, nx, ny, ox, oy, INV_PAINT, 1,
  1231. X          RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1232. X    ox = nx;
  1233. X    oy = ny;
  1234. X    }
  1235. X    pw_vector(canvas_win, ox, oy, x2, y2, INV_PAINT, 1,
  1236. X          RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1237. X}
  1238. X
  1239. Xresizing_poly(x, y)
  1240. X    int            x, y;
  1241. X{
  1242. X    elastic_poly(fix_x, fix_y, cur_x, cur_y, work_numsides);
  1243. X    cur_x = x;
  1244. X    cur_y = y;
  1245. X    work_numsides = cur_numsides;
  1246. X    elastic_poly(fix_x, fix_y, cur_x, cur_y, work_numsides);
  1247. X    length_msg(MSG_LENGTH);
  1248. X}
  1249. X
  1250. X/*********************** ELLIPSES *************************/
  1251. X
  1252. Xelastic_ebr()
  1253. X{
  1254. X    register int    x1, y1, x2, y2;
  1255. X    int            rx, ry;
  1256. X
  1257. X    rx = cur_x - fix_x;
  1258. X    ry = cur_y - fix_y;
  1259. X    if (cur_angle != 0.0) {
  1260. X    angle_ellipse(fix_x, fix_y, rx, ry, cur_angle,
  1261. X          INV_PAINT, 1, RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1262. X    } else {
  1263. X    x1 = fix_x + rx;
  1264. X    x2 = fix_x - rx;
  1265. X    y1 = fix_y + ry;
  1266. X    y2 = fix_y - ry;
  1267. X    pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, 1,
  1268. X         RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1269. X    }
  1270. X}
  1271. X
  1272. Xresizing_ebr(x, y)
  1273. X    int            x, y;
  1274. X{
  1275. X    elastic_ebr();
  1276. X    cur_x = x;
  1277. X    cur_y = y;
  1278. X    elastic_ebr();
  1279. X    length_msg(MSG_RADIUS);
  1280. X}
  1281. X
  1282. Xconstrained_resizing_ebr(x, y)
  1283. X    int            x, y;
  1284. X{
  1285. X    elastic_ebr();
  1286. X    adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  1287. X    elastic_ebr();
  1288. X    length_msg(MSG_RADIUS);
  1289. X}
  1290. X
  1291. Xelastic_ebd()
  1292. X{
  1293. X    int            centx,centy;
  1294. X    centx = (fix_x+cur_x)/2;
  1295. X    centy = (fix_y+cur_y)/2;
  1296. X    if (cur_angle != 0.0) {
  1297. X    angle_ellipse(centx, centy, abs(cur_x-fix_x)/2, 
  1298. X          abs(cur_y-fix_y)/2, cur_angle,
  1299. X          INV_PAINT, 1, RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1300. X    } else {
  1301. X    pw_curve(canvas_win, fix_x, fix_y, cur_x, cur_y,
  1302. X         INV_PAINT, 1, RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1303. X    }
  1304. X    length_msg(MSG_DIAM);
  1305. X}
  1306. X
  1307. Xresizing_ebd(x, y)
  1308. X    int            x, y;
  1309. X{
  1310. X    elastic_ebd();
  1311. X    cur_x = x;
  1312. X    cur_y = y;
  1313. X    elastic_ebd();
  1314. X    length_msg(MSG_DIAM);
  1315. X}
  1316. X
  1317. Xconstrained_resizing_ebd(x, y)
  1318. X    int            x, y;
  1319. X{
  1320. X    elastic_ebd();
  1321. X    adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  1322. X    elastic_ebd();
  1323. X    length_msg(MSG_DIAM);
  1324. X}
  1325. X
  1326. Xelastic_cbr()
  1327. X{
  1328. X    register int    radius, x1, y1, x2, y2, rx, ry;
  1329. X
  1330. X    rx = cur_x - fix_x;
  1331. X    ry = cur_y - fix_y;
  1332. X    radius = round(sqrt((double) (rx * rx + ry * ry)));
  1333. X    x1 = fix_x + radius;
  1334. X    x2 = fix_x - radius;
  1335. X    y1 = fix_y + radius;
  1336. X    y2 = fix_y - radius;
  1337. X    pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, 1,
  1338. X         RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1339. X}
  1340. X
  1341. Xresizing_cbr(x, y)
  1342. X    int            x, y;
  1343. X{
  1344. X    elastic_cbr();
  1345. X    cur_x = x;
  1346. X    cur_y = y;
  1347. X    elastic_cbr();
  1348. X    length_msg(MSG_RADIUS);
  1349. X}
  1350. X
  1351. Xelastic_cbd()
  1352. X{
  1353. X    register int    x1, y1, x2, y2;
  1354. X    int            radius, rx, ry;
  1355. X
  1356. X    rx = (cur_x - fix_x) / 2;
  1357. X    ry = (cur_y - fix_y) / 2;
  1358. X    radius = round(sqrt((double) (rx * rx + ry * ry)));
  1359. X    x1 = fix_x + rx + radius;
  1360. X    x2 = fix_x + rx - radius;
  1361. X    y1 = fix_y + ry + radius;
  1362. X    y2 = fix_y + ry - radius;
  1363. X    pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, 1,
  1364. X         RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1365. X}
  1366. X
  1367. Xresizing_cbd(x, y)
  1368. X    int            x, y;
  1369. X{
  1370. X    elastic_cbd();
  1371. X    cur_x = x;
  1372. X    cur_y = y;
  1373. X    elastic_cbd();
  1374. X    length_msg(MSG_DIAM);
  1375. X}
  1376. X
  1377. Xconstrained_resizing_cbd(x, y)
  1378. X    int            x, y;
  1379. X{
  1380. X    elastic_cbd();
  1381. X    adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  1382. X    elastic_cbd();
  1383. X    length_msg(MSG_DIAM);
  1384. X}
  1385. X
  1386. Xelastic_moveellipse()
  1387. X{
  1388. X    register int    x1, y1, x2, y2;
  1389. X
  1390. X    x1 = cur_x + x1off;
  1391. X    x2 = cur_x + x2off;
  1392. X    y1 = cur_y + y1off;
  1393. X    y2 = cur_y + y2off;
  1394. X    if (cur_angle != 0.0) {
  1395. X    angle_ellipse((x1+x2)/2, (y1+y2)/2, abs(x1-x2)/2, abs(y1-y2)/2, cur_angle,
  1396. X          INV_PAINT, 1, RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1397. X    } else {
  1398. X    pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, 1,
  1399. X         RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1400. X    }
  1401. X}
  1402. X
  1403. Xmoving_ellipse(x, y)
  1404. X    int            x, y;
  1405. X{
  1406. X    elastic_moveellipse();
  1407. X    adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1408. X    elastic_moveellipse();
  1409. X}
  1410. X
  1411. Xelastic_scaleellipse(e)
  1412. X    F_ellipse       *e;
  1413. X{
  1414. X    register int    x1, y1, x2, y2;
  1415. X    int            rx, ry;
  1416. X    int            newx, newy, oldx, oldy;
  1417. X    float        newd, oldd, scalefact;
  1418. X
  1419. X    newx = cur_x - fix_x;
  1420. X    newy = cur_y - fix_y;
  1421. X    newd = sqrt((double) (newx * newx + newy * newy));
  1422. X
  1423. X    oldx = from_x - fix_x;
  1424. X    oldy = from_y - fix_y;
  1425. X    oldd = sqrt((double) (oldx * oldx + oldy * oldy));
  1426. X
  1427. X    scalefact = newd / oldd;
  1428. X
  1429. X    rx = e->radiuses.x * scalefact;
  1430. X    ry = e->radiuses.y * scalefact;
  1431. X    if (cur_angle != 0.0) {
  1432. X    angle_ellipse(e->center.x, e->center.y, rx, ry, cur_angle,
  1433. X          INV_PAINT, 1, RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1434. X    } else {
  1435. X    x1 = fix_x + rx;
  1436. X    x2 = fix_x - rx;
  1437. X    y1 = fix_y + ry;
  1438. X    y2 = fix_y - ry;
  1439. X    pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, 1,
  1440. X         RUBBER_LINE, 0.0, 0, DEFAULT_COLOR);
  1441. X    }
  1442. X}
  1443. X
  1444. Xscaling_ellipse(x, y)
  1445. X    int            x, y;
  1446. X{
  1447. X    elastic_scaleellipse(cur_e);
  1448. X    adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1449. X    elastic_scaleellipse(cur_e);
  1450. X}
  1451. X
  1452. X/*************************** ARCS *************************/
  1453. X
  1454. Xreshaping_arc(x, y)
  1455. X    int            x, y;
  1456. X{
  1457. X    elastic_arclink();
  1458. X    adjust_pos(x, y, cur_a->point[movedpoint_num].x,
  1459. X           cur_a->point[movedpoint_num].y, &cur_x, &cur_y);
  1460. X    elastic_arclink();
  1461. X    if (movedpoint_num == 1) {
  1462. X    /* middle point */
  1463. X    length_msg2(cur_a->point[0].x, cur_a->point[0].y,
  1464. X            cur_a->point[2].x, cur_a->point[2].y,
  1465. X            cur_x, cur_y);
  1466. X    } else {
  1467. X    /* end point */
  1468. X    altlength_msg(MSG_LENGTH,cur_a->point[1].x,cur_a->point[1].y);
  1469. X    }
  1470. X}
  1471. X
  1472. Xelastic_arclink()
  1473. X{
  1474. X    switch (movedpoint_num) {
  1475. X    case 0:
  1476. X    pw_vector(canvas_win, cur_x, cur_y,
  1477. X          cur_a->point[1].x, cur_a->point[1].y,
  1478. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1479. X    break;
  1480. X    case 1:
  1481. X    pw_vector(canvas_win, cur_a->point[0].x, cur_a->point[0].y,
  1482. X          cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  1483. X          DEFAULT_COLOR);
  1484. X    pw_vector(canvas_win, cur_a->point[2].x, cur_a->point[2].y,
  1485. X          cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  1486. X          DEFAULT_COLOR);
  1487. X    break;
  1488. X    default:
  1489. X    pw_vector(canvas_win, cur_a->point[1].x, cur_a->point[1].y,
  1490. X          cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  1491. X          DEFAULT_COLOR);
  1492. X    }
  1493. X}
  1494. X
  1495. Xmoving_arc(x, y)
  1496. X    int            x, y;
  1497. X{
  1498. X    elastic_movearc(new_a);
  1499. X    adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1500. X    elastic_movearc(new_a);
  1501. X}
  1502. X
  1503. Xelastic_movearc(a)
  1504. X    F_arc       *a;
  1505. X{
  1506. X    int            dx, dy;
  1507. X
  1508. X    dx = cur_x - fix_x;
  1509. X    dy = cur_y - fix_y;
  1510. X    pw_vector(canvas_win, a->point[0].x + dx, a->point[0].y + dy,
  1511. X          a->point[1].x + dx, a->point[1].y + dy,
  1512. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1513. X    pw_vector(canvas_win, a->point[1].x + dx, a->point[1].y + dy,
  1514. X          a->point[2].x + dx, a->point[2].y + dy,
  1515. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1516. X}
  1517. X
  1518. Xscaling_arc(x, y)
  1519. X    int            x, y;
  1520. X{
  1521. X    elastic_scalearc(cur_a);
  1522. X    adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1523. X    elastic_scalearc(cur_a);
  1524. X}
  1525. X
  1526. Xelastic_scalearc(a)
  1527. X    F_arc       *a;
  1528. X{
  1529. X    int            newx, newy, oldx, oldy;
  1530. X    float        newd, oldd, scalefact;
  1531. X    F_pos        p0, p1, p2;
  1532. X
  1533. X    newx = cur_x - fix_x;
  1534. X    newy = cur_y - fix_y;
  1535. X    newd = sqrt((double) (newx * newx + newy * newy));
  1536. X
  1537. X    oldx = from_x - fix_x;
  1538. X    oldy = from_y - fix_y;
  1539. X    oldd = sqrt((double) (oldx * oldx + oldy * oldy));
  1540. X
  1541. X    scalefact = newd / oldd;
  1542. X
  1543. X    p0 = a->point[0];
  1544. X    p1 = a->point[1];
  1545. X    p2 = a->point[2];
  1546. X    p0.x = fix_x + (p0.x - fix_x) * scalefact;
  1547. X    p0.y = fix_y + (p0.y - fix_y) * scalefact;
  1548. X    p1.x = fix_x + (p1.x - fix_x) * scalefact;
  1549. X    p1.y = fix_y + (p1.y - fix_y) * scalefact;
  1550. X    p2.x = fix_x + (p2.x - fix_x) * scalefact;
  1551. X    p2.y = fix_y + (p2.y - fix_y) * scalefact;
  1552. X
  1553. X    pw_vector(canvas_win, p0.x, p0.y, p1.x, p1.y,
  1554. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1555. X    pw_vector(canvas_win, p1.x, p1.y, p2.x, p2.y,
  1556. X          INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT_COLOR);
  1557. X}
  1558. X
  1559. X/*************************** TEXT *************************/
  1560. X
  1561. Xmoving_text(x, y)
  1562. X    int            x, y;
  1563. X{
  1564. X    elastic_movetext();
  1565. X    adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1566. X    elastic_movetext();
  1567. X}
  1568. X
  1569. Xelastic_movetext()
  1570. X{
  1571. X    pw_text(canvas_win, cur_x + x1off, cur_y + y1off, INV_PAINT,
  1572. X        new_t->fontstruct, new_t->cstring, new_t->color);
  1573. X}
  1574. X
  1575. X
  1576. X/*************************** SPLINES *************************/
  1577. X
  1578. Xmoving_spline(x, y)
  1579. X    int            x, y;
  1580. X{
  1581. X    elastic_moveline(new_s->points);
  1582. X    adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
  1583. X    elastic_moveline(new_s->points);
  1584. X}
  1585. X
  1586. X/*********** AUXILIARY FUNCTIONS FOR CONSTRAINED MOVES ******************/
  1587. X
  1588. Xadjust_box_pos(curs_x, curs_y, orig_x, orig_y, ret_x, ret_y)
  1589. X    int            curs_x, curs_y, orig_x, orig_y;
  1590. X    int           *ret_x, *ret_y;
  1591. X{
  1592. X    int            xx, sgn_csr2fix_x, yy, sgn_csr2fix_y;
  1593. X    double        mag_csr2fix_x, mag_csr2fix_y;
  1594. X
  1595. X    switch (constrained) {
  1596. X    case MOVE_ARB:
  1597. X    *ret_x = curs_x;
  1598. X    *ret_y = curs_y;
  1599. X    break;
  1600. X    case BOX_HSTRETCH:
  1601. X    *ret_x = curs_x;
  1602. X    *ret_y = orig_y;
  1603. X    break;
  1604. X    case BOX_VSTRETCH:
  1605. X    *ret_x = orig_x;
  1606. X    *ret_y = curs_y;
  1607. X    break;
  1608. X    default:
  1609. X    /* calculate where scaled and stretched box corners would be */
  1610. X    xx = curs_x - fix_x;
  1611. X    sgn_csr2fix_x = signof(xx);
  1612. X    mag_csr2fix_x = (double) abs(xx);
  1613. X
  1614. X    yy = curs_y - fix_y;
  1615. X    sgn_csr2fix_y = signof(yy);
  1616. X    mag_csr2fix_y = (double) abs(yy);
  1617. X
  1618. X    if (mag_csr2fix_x * sina > mag_csr2fix_y * cosa) {    /* above diagonal */
  1619. X        *ret_x = curs_x;
  1620. X        if (constrained == BOX_SCALE) {
  1621. X        if (cosa == 0.0) {
  1622. X            *ret_y = fix_y + sgn_csr2fix_y * (int) (mag_csr2fix_x);
  1623. X        } else {
  1624. X            *ret_y = fix_y + sgn_csr2fix_y * (int) (mag_csr2fix_x * sina / cosa);
  1625. X        }
  1626. X        } else {
  1627. X            *ret_y = fix_y + sgn_csr2fix_y * abs(fix_y - orig_y);
  1628. X         }
  1629. X    } else {
  1630. X        *ret_y = curs_y;
  1631. X        if (constrained == BOX_SCALE) {
  1632. X        if (sina == 0.0) {
  1633. X            *ret_x = fix_x + sgn_csr2fix_x * (int) (mag_csr2fix_y);
  1634. X        } else {
  1635. X            *ret_x = fix_x + sgn_csr2fix_x * (int) (mag_csr2fix_y * cosa / sina);
  1636. X        }
  1637. X        } else {
  1638. X        *ret_x = fix_x + sgn_csr2fix_x * abs(fix_x - orig_x);
  1639. X        }
  1640. X    }
  1641. X    } /* switch */
  1642. X}
  1643. X
  1644. Xadjust_pos(curs_x, curs_y, orig_x, orig_y, ret_x, ret_y)
  1645. X    int            curs_x, curs_y, orig_x, orig_y;
  1646. X    int           *ret_x, *ret_y;
  1647. X{
  1648. X    if (constrained) {
  1649. X    if (abs(orig_x - curs_x) > abs(orig_y - curs_y)) {
  1650. X        *ret_x = curs_x;
  1651. X        *ret_y = orig_y;
  1652. X    } else {
  1653. X        *ret_x = orig_x;
  1654. X        *ret_y = curs_y;
  1655. X    }
  1656. X    } else {
  1657. X    *ret_x = curs_x;
  1658. X    *ret_y = curs_y;
  1659. X    }
  1660. X}
  1661. END_OF_FILE
  1662. if test 20435 -ne `wc -c <'u_elastic.c'`; then
  1663.     echo shar: \"'u_elastic.c'\" unpacked with wrong size!
  1664. fi
  1665. # end of 'u_elastic.c'
  1666. fi
  1667. if test -f 'w_rottext.c' -a "${1}" != "-c" ; then 
  1668.   echo shar: Will not clobber existing file \"'w_rottext.c'\"
  1669. else
  1670. echo shar: Extracting \"'w_rottext.c'\" \(21004 characters\)
  1671. sed "s/^X//" >'w_rottext.c' <<'END_OF_FILE'
  1672. X/*
  1673. X * FIG : Facility for Interactive Generation of figures
  1674. X * Copyright (c) 1992 by Alan Richardson
  1675. X *
  1676. X * "Permission to use, copy, modify, distribute, and sell this software and its
  1677. X * documentation for any purpose is hereby granted without fee, provided that
  1678. X * the above copyright notice appear in all copies and that both the copyright
  1679. X * notice and this permission notice appear in supporting documentation. 
  1680. X * No representations are made about the suitability of this software for 
  1681. X * any purpose.  It is provided "as is" without express or implied warranty."
  1682. X */
  1683. X
  1684. X#include "fig.h"
  1685. X#include "w_rottext.h"
  1686. X
  1687. X/* ---------------------------------------------------------------------- */
  1688. X
  1689. X#define XROTMAX(a, b) ((a)>(b)?(a):(b))
  1690. X
  1691. X/* ---------------------------------------------------------------------- */
  1692. X
  1693. Xchar            *my_strdup();
  1694. Xchar            *my_strtok();
  1695. XXRotFontStruct         *XRotLoadFont();
  1696. Xvoid              XRotUnloadFont();
  1697. Xint               XRotTextWidth();
  1698. Xint               XRotTextHeight();
  1699. Xvoid             XRotDrawString();
  1700. Xvoid               XRotDrawImageString();
  1701. Xvoid                     XRotPaintString();
  1702. Xvoid               XRotDrawAlignedString();
  1703. Xvoid                     XRotDrawAlignedImageString();
  1704. Xvoid                     XRotPaintAlignedString();
  1705. X
  1706. X/* ---------------------------------------------------------------------- */
  1707. X  
  1708. X/* *** Routine to mimic `strdup()' (some machines don't have it) *** */
  1709. X
  1710. Xchar *my_strdup(str)
  1711. X char *str;
  1712. X{
  1713. X char *s;
  1714. X
  1715. X if(str==NULL) return (char *)NULL;
  1716. X
  1717. X s=(char *)malloc((unsigned)(strlen(str)+1));
  1718. X if(!s)
  1719. X  { fprintf(stderr, "Error: my_strdup(): Couldn't do malloc\n");
  1720. X    exit(1); }
  1721. X
  1722. X strcpy(s, str);
  1723. X
  1724. X return s;
  1725. X}
  1726. X
  1727. X
  1728. X/* ---------------------------------------------------------------------- */
  1729. X
  1730. X
  1731. X/* *** Routine to replace `strtok' : this one returns a zero
  1732. X       length string if it encounters two consecutive delimiters *** */
  1733. X
  1734. Xchar *my_strtok(str1, str2)
  1735. X char *str1, *str2;
  1736. X{
  1737. X char *ret;
  1738. X int i, j, stop;
  1739. X static int start, len;
  1740. X static char *stext;
  1741. X
  1742. X if(str2==NULL)
  1743. X  { fprintf(stderr, "Error: my_strtok(): null delimiter string\n");
  1744. X    exit(1);
  1745. X  }
  1746. X
  1747. X /* initialise if str1 not NULL ... */
  1748. X if(str1!=NULL)
  1749. X  { start=0;
  1750. X    stext=str1;
  1751. X    len=strlen(str1);
  1752. X  }
  1753. X
  1754. X /* run out of tokens ? ... */
  1755. X if(start>=len) return (char *)NULL;
  1756. X
  1757. X /* loop through characters ... */
  1758. X for(i=start; i<len; i++)
  1759. X {
  1760. X  /* loop through delimiters ... */
  1761. X  stop=0;
  1762. X  for(j=0; j<strlen(str2); j++) if(stext[i]==str2[j]) stop=1;
  1763. X
  1764. X  if(stop) break;
  1765. X }
  1766. X
  1767. X stext[i]='\0';
  1768. X
  1769. X ret=stext+start;
  1770. X
  1771. X start=i+1;
  1772. X
  1773. X return ret;
  1774. X}
  1775. X
  1776. X
  1777. X/* ---------------------------------------------------------------------- */
  1778. X  
  1779. X
  1780. X/* *** Load the rotated version of a given font *** */
  1781. XXRotFontStruct *XRotLoadFont(dpy, fontname, angle)
  1782. X Display *dpy;
  1783. X char *fontname;
  1784. X float angle;
  1785. X{
  1786. X char         val;
  1787. X XImage        *I1, *I2;
  1788. X Pixmap         canvas;
  1789. X Window         root;
  1790. X int         screen;
  1791. X GC         font_gc;
  1792. X char         text[3];
  1793. X XFontStruct    *fontstruct;
  1794. X XRotFontStruct    *rotfont;
  1795. X int         ichar, i, j, index, boxlen, dir;
  1796. X int         vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
  1797. X int         min_char, max_char;
  1798. X unsigned char    *vertdata, *bitdata;
  1799. X int         ascent, descent, lbearing, rbearing;
  1800. X int         on=1, off=0;
  1801. X
  1802. X dir=(int)(angle/90.0+0.01);
  1803. X if (dir > 3)
  1804. X    dir -= 4;
  1805. X
  1806. X /* useful macros ... */
  1807. X screen=DefaultScreen(dpy);
  1808. X root=DefaultRootWindow(dpy);
  1809. X
  1810. X /* load the font ... */
  1811. X fontstruct=XLoadQueryFont(dpy, fontname);
  1812. X if(!fontstruct) { 
  1813. X    fprintf(stderr,
  1814. X            "Error: XRotLoadFont(): XServer couldn't load the font `%s'\n",
  1815. X            fontname);
  1816. X    exit(1); 
  1817. X }
  1818. X /* boxlen is the square size that would enclose the largest character */
  1819. X boxlen = max2(fontstruct->max_bounds.rbearing - fontstruct->max_bounds.lbearing, 
  1820. X          fontstruct->max_bounds.ascent + fontstruct->max_bounds.descent);
  1821. X boxlen *= 2;
  1822. X
  1823. X /* create the depth 1 canvas bitmap ... */
  1824. X canvas=XCreatePixmap(dpy, root, boxlen, boxlen, 1);
  1825. X /* create a GC ... */
  1826. X font_gc=XCreateGC(dpy, canvas, NULL, 0);
  1827. X XSetBackground(dpy, font_gc, off);
  1828. X
  1829. X XSetFont(dpy, font_gc, fontstruct->fid);
  1830. X
  1831. X /* allocate space for rotated font ... */
  1832. X rotfont=(XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct));
  1833. X if(!rotfont) { 
  1834. X    fprintf(stderr,"Error: XRotLoadFont(): Couldn't do malloc\n");
  1835. X    exit(1); 
  1836. X }
  1837. X   
  1838. X /* determine which characters are defined in font ... */
  1839. X min_char=fontstruct->min_char_or_byte2; 
  1840. X max_char=fontstruct->max_char_or_byte2;
  1841. X /* we only want printing characters ... */
  1842. X if(min_char<32)  min_char=32;
  1843. X if(max_char>126) max_char=126;
  1844. X     
  1845. X /* some overall font data ... */
  1846. X rotfont->name=my_strdup(fontname);
  1847. X rotfont->dir=dir;
  1848. X rotfont->min_char=min_char;
  1849. X rotfont->max_char=max_char;
  1850. X rotfont->max_ascent=fontstruct->max_bounds.ascent;
  1851. X rotfont->max_descent=fontstruct->max_bounds.descent;   
  1852. X rotfont->height=rotfont->max_ascent+rotfont->max_descent;
  1853. X rotfont->width=fontstruct->max_bounds.width;
  1854. X
  1855. X /* remember xfontstruct for `normal' text ... */
  1856. X if(dir==0) 
  1857. X    rotfont->xfontstruct=fontstruct;
  1858. X
  1859. X /* loop through each character ... */
  1860. X for(ichar=min_char; ichar<=max_char; ichar++) {
  1861. X
  1862. X     index=ichar-fontstruct->min_char_or_byte2;
  1863. X     /* per char dimensions ... */
  1864. X     ascent=  rotfont->per_char[ichar-32].ascent=
  1865. X                      fontstruct->per_char[index].ascent;
  1866. X     descent= rotfont->per_char[ichar-32].descent=
  1867. X                      fontstruct->per_char[index].descent;
  1868. X     lbearing=rotfont->per_char[ichar-32].lbearing=
  1869. X                      fontstruct->per_char[index].lbearing;
  1870. X     rbearing=rotfont->per_char[ichar-32].rbearing=
  1871. X                      fontstruct->per_char[index].rbearing;
  1872. X              rotfont->per_char[ichar-32].width=
  1873. X                      fontstruct->per_char[index].width;
  1874. X
  1875. X     /* no need for the following with normal text */
  1876. X     if (dir == 0)
  1877. X    continue;
  1878. X
  1879. X     /* some space chars have zero body, but a bitmap can't have ... */
  1880. X     if(!ascent && !descent)   
  1881. X            ascent=  rotfont->per_char[ichar-32].ascent=  1;
  1882. X     if(!lbearing && !rbearing) 
  1883. X            rbearing=rotfont->per_char[ichar-32].rbearing=1;
  1884. X
  1885. X     /* glyph width and height when vertical ... */
  1886. X     vert_w=rbearing-lbearing;
  1887. X     vert_h=ascent+descent;
  1888. X
  1889. X     /* width in bytes ... */
  1890. X     vert_len=(vert_w-1)/8+1;   
  1891. X     XSetForeground(dpy, font_gc, off);
  1892. X     XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
  1893. X
  1894. X     /* draw the character centre top right on canvas ... */
  1895. X     sprintf(text, "%c", ichar);
  1896. X     XSetForeground(dpy, font_gc, on);
  1897. X     XDrawImageString(dpy, canvas, font_gc, boxlen/2-lbearing,
  1898. X                      boxlen/2-descent, text, 1);
  1899. X
  1900. X     /* reserve memory for first XImage ... */
  1901. X     vertdata=(unsigned char *) malloc((unsigned)(vert_len*vert_h));
  1902. X     if(!vertdata) { 
  1903. X    fprintf(stderr,"Error: XRotLoadFont(): Couldn't do malloc\n");
  1904. X        exit(1); 
  1905. X      }
  1906. X  
  1907. X     /* create the XImage ... */
  1908. X     I1=XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
  1909. X                     0, (char *) vertdata, vert_w, vert_h, 8, 0);
  1910. X
  1911. X     if(!I1) { 
  1912. X    fprintf(stderr,"Error: XRotLoadFont(): Couldn't create XImage\n");
  1913. X        exit(1); 
  1914. X     }
  1915. X  
  1916. X     I1->byte_order=I1->bitmap_bit_order=MSBFirst;
  1917. X
  1918. X     /* extract character from canvas ... */
  1919. X     XGetSubImage(dpy, canvas, boxlen/2, boxlen/2-vert_h,
  1920. X                  vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
  1921. X     I1->format=XYBitmap; 
  1922. X     /* width, height of rotated character ... */
  1923. X     if(dir==2) { 
  1924. X    bit_w=vert_w; bit_h=vert_h; 
  1925. X     } else { 
  1926. X    bit_w=vert_h; bit_h=vert_w; 
  1927. X     }
  1928. X
  1929. X     /* width in bytes ... */
  1930. X     bit_len=(bit_w-1)/8+1;
  1931. X   
  1932. X     rotfont->per_char[ichar-32].glyph.bit_w=bit_w;
  1933. X     rotfont->per_char[ichar-32].glyph.bit_h=bit_h;
  1934. X
  1935. X     /* reserve memory for the rotated image ... */
  1936. X     bitdata=(unsigned char *)calloc((unsigned)(bit_h*bit_len), 1);
  1937. X     if(!bitdata) { 
  1938. X    fprintf(stderr,"Error: XRotLoadFont(): Couldn't do calloc\n");
  1939. X        exit(1); 
  1940. X     }
  1941. X
  1942. X     /* create the image ... */
  1943. X     I2=XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
  1944. X                     (char *) bitdata, bit_w, bit_h, 8, 0); 
  1945. X     if(!I2) { 
  1946. X    fprintf(stderr,"Error: XRotLoadFont(): Couldn't create XImage\n");
  1947. X        exit(1);
  1948. X     }
  1949. X
  1950. X     I2->byte_order=I2->bitmap_bit_order=MSBFirst;
  1951. X
  1952. X     /* map vertical data to rotated character ... */
  1953. X     for(j=0; j<bit_h; j++) {
  1954. X      for(i=0; i<bit_w; i++) {
  1955. X       /* map bits ... */
  1956. X       if(dir==1)
  1957. X         val=vertdata[i*vert_len + (vert_w-j-1)/8] & (128>>((vert_w-j-1)%8));
  1958. X   
  1959. X       else if(dir==2)
  1960. X         val=vertdata[(vert_h-j-1)*vert_len + (vert_w-i-1)/8] &
  1961. X                                                       (128>>((vert_w-i-1)%8));
  1962. X       else 
  1963. X         val=vertdata[(vert_h-i-1)*vert_len + j/8] & (128>>(j%8));
  1964. X        
  1965. X       if(val) bitdata[j*bit_len + i/8] = 
  1966. X                   bitdata[j*bit_len + i/8]|(128>>(i%8));
  1967. X      }
  1968. X     }
  1969. X   
  1970. X     /* create this character's bitmap ... */
  1971. X     rotfont->per_char[ichar-32].glyph.bm=
  1972. X       XCreatePixmap(dpy, root, bit_w, bit_h, 1);
  1973. X     
  1974. X     /* put the image into the bitmap ... */
  1975. X     XPutImage(dpy, rotfont->per_char[ichar-32].glyph.bm, 
  1976. X               font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
  1977. X  
  1978. X     /* free the image and data ... */
  1979. X     XDestroyImage(I1);
  1980. X     XDestroyImage(I2);
  1981. X     free((char *)bitdata);
  1982. X     free((char *)vertdata);
  1983. X }
  1984. X
  1985. X if (dir != 0)
  1986. X    XFreeFont(dpy, fontstruct);
  1987. X
  1988. X /* free pixmap and GC ... */
  1989. X XFreePixmap(dpy, canvas);
  1990. X XFreeGC(dpy, font_gc);
  1991. X
  1992. X return rotfont;
  1993. X}
  1994. X
  1995. X
  1996. X/* ---------------------------------------------------------------------- */
  1997. X
  1998. X
  1999. X/* *** Free the resources associated with a rotated font *** */
  2000. X
  2001. Xvoid XRotUnloadFont(dpy, rotfont)
  2002. X Display *dpy;
  2003. X XRotFontStruct *rotfont;
  2004. X{
  2005. X int ichar;
  2006. X
  2007. X if(rotfont->dir==0) XFreeFont(dpy, rotfont->xfontstruct);
  2008. X
  2009. X else
  2010. X  /* loop through each character, freeing its pixmap ... */
  2011. X  for(ichar=rotfont->min_char-32; ichar<=rotfont->max_char-32; ichar++)
  2012. X    XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm);
  2013. X
  2014. X /* rotfont should never be referenced again ... */
  2015. X free((char *)rotfont);
  2016. X}
  2017. X
  2018. X
  2019. X/* ---------------------------------------------------------------------- */
  2020. X   
  2021. X
  2022. X/* *** Return the width of a string *** */
  2023. X
  2024. Xint XRotTextWidth(rotfont, str, len)
  2025. X XRotFontStruct *rotfont;
  2026. X char *str;
  2027. X int len;
  2028. X{
  2029. X int i, width=0, ichar;
  2030. X
  2031. X if(str==NULL) 
  2032. X    return 0;
  2033. X
  2034. X if(rotfont->dir==0)
  2035. X    width=XTextWidth(rotfont->xfontstruct, str, len);
  2036. X
  2037. X else
  2038. X  for(i=0; i<len; i++) {
  2039. X   ichar=str[i]-32;
  2040. X  
  2041. X   /* make sure it's a printing character ... */
  2042. X   if((ichar>=0)&&(ichar<95)) 
  2043. X    width+=rotfont->per_char[ichar].width;
  2044. X  }
  2045. X
  2046. X return width;
  2047. X}
  2048. X
  2049. X/* *** Return the height of a string *** */
  2050. X
  2051. Xint XRotTextHeight(rotfont, str, len)
  2052. X XRotFontStruct *rotfont;
  2053. X char *str;
  2054. X int len;
  2055. X{
  2056. X int i, height=0, ichar;
  2057. X int maxasc=0;
  2058. X int maxdsc=0;
  2059. X int dum;
  2060. X XCharStruct ch;
  2061. X
  2062. X if(str==NULL) return 0;
  2063. X
  2064. X if(rotfont->dir==0) {
  2065. X    XTextExtents(rotfont->xfontstruct, str, len, &dum,&dum,&dum,&ch);
  2066. X    height = ch.ascent + ch.descent;
  2067. X }
  2068. X else
  2069. X  for(i=0; i<len; i++)
  2070. X  {
  2071. X   ichar=str[i]-32;
  2072. X  
  2073. X   /* make sure it's a printing character ... */
  2074. X   /* then find the highest and most descending */
  2075. X   if((ichar>=0)&&(ichar<95)) {
  2076. X    maxasc=max2(maxasc,rotfont->per_char[ichar].ascent);
  2077. X    maxdsc=max2(maxdsc,rotfont->per_char[ichar].descent);
  2078. X   }
  2079. X   /* and add the two together */
  2080. X   height = maxasc+maxdsc;
  2081. X  }
  2082. X
  2083. X return height;
  2084. X}
  2085. X
  2086. X
  2087. X/* ---------------------------------------------------------------------- */
  2088. X
  2089. X
  2090. X/* *** A front end to XRotPaintString : mimics XDrawString *** */
  2091. X
  2092. Xvoid XRotDrawString(dpy,  drawable, rotfont,gc, x, y, str, len)
  2093. X Display *dpy;
  2094. X Drawable drawable;
  2095. X XRotFontStruct *rotfont;
  2096. X GC gc;
  2097. X int x, y;
  2098. X char *str;
  2099. X int len;
  2100. X{
  2101. X XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, 0);
  2102. X}
  2103. X
  2104. X
  2105. X/* ---------------------------------------------------------------------- */
  2106. X
  2107. X/* *** A front end to XRotPaintString : mimics XDrawImageString *** */
  2108. X
  2109. Xvoid XRotDrawImageString(dpy,  drawable, rotfont, gc, x, y, str, len)
  2110. X Display *dpy;
  2111. X Drawable drawable;
  2112. X XRotFontStruct *rotfont;
  2113. X GC gc;
  2114. X int x, y;
  2115. X char *str;
  2116. X int len;
  2117. X{
  2118. X XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, 1);
  2119. X}
  2120. X
  2121. X
  2122. X/* ---------------------------------------------------------------------- */
  2123. X              
  2124. X              
  2125. X/* *** Paint a simple string with a rotated font *** */
  2126. X
  2127. X/* *** The user should use one of the two front ends above *** */
  2128. X
  2129. Xvoid XRotPaintString(dpy,  drawable, rotfont, gc, x, y, str, len, paintbg)
  2130. X Display *dpy;
  2131. X Drawable drawable;
  2132. X XRotFontStruct *rotfont;
  2133. X GC gc;
  2134. X int x, y;
  2135. X char *str;
  2136. X int len;
  2137. X int paintbg;
  2138. X{            
  2139. X static GC my_gc=NULL;
  2140. X XGCValues values;
  2141. X int i, xp, yp, dir, ichar, width;
  2142. X#ifdef X11R3
  2143. X static Pixmap empty_stipple=(Pixmap)NULL;
  2144. X#endif
  2145. X
  2146. X dir=rotfont->dir;
  2147. X
  2148. X if(!my_gc) my_gc=XCreateGC(dpy, drawable, NULL, 0);
  2149. X
  2150. X XCopyGC(dpy, gc, GCFunction|GCForeground|GCBackground, my_gc);
  2151. X
  2152. X /* a horizontal string is easy ... */
  2153. X if(dir==0)
  2154. X  { XSetFillStyle(dpy, my_gc, FillSolid);
  2155. X    XSetFont(dpy, my_gc, rotfont->xfontstruct->fid);
  2156. X    if(!paintbg) XDrawString(dpy, drawable, my_gc, x, y, str, len);
  2157. X    else         XDrawImageString(dpy, drawable, my_gc, x, y, str, len);
  2158. X
  2159. X    return;
  2160. X  }
  2161. X
  2162. X /* vertical or upside down ... */
  2163. X
  2164. X /* to draw an `image string' we need to fill the background ... */
  2165. X if(paintbg)
  2166. X  {
  2167. X#ifdef X11R3
  2168. X   /* Release 3 doesn't have XGetGCValues(), so this is a
  2169. X      slightly slower fudge ... */
  2170. X   {
  2171. X    GC stipple_gc;
  2172. X    int bestw, besth;
  2173. X
  2174. X    if(!empty_stipple)    
  2175. X     { XQueryBestStipple(dpy, drawable, 1, 1, &bestw, &besth);
  2176. X       empty_stipple=XCreatePixmap(dpy, drawable, bestw, besth, 1);
  2177. X
  2178. X       stipple_gc=XCreateGC(dpy, empty_stipple, NULL, 0);
  2179. X       XSetForeground(dpy, stipple_gc, 0);
  2180. X
  2181. X       XFillRectangle(dpy, empty_stipple, stipple_gc, 0, 0, bestw+1, besth+1);
  2182. X       XFreeGC(dpy, stipple_gc);
  2183. X     }
  2184. X
  2185. X     XSetStipple(dpy, my_gc, empty_stipple);
  2186. X     XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
  2187. X   }    
  2188. X#else
  2189. X   /* get the foreground and background colors
  2190. X        ( note that this is not a round trip -> little speed penalty ) */
  2191. X   XGetGCValues(dpy, my_gc, GCForeground|GCBackground, &values);
  2192. X
  2193. X   XSetForeground(dpy, my_gc, values.background);
  2194. X   XSetFillStyle(dpy, my_gc, FillSolid);
  2195. X#endif
  2196. X
  2197. X   width=XRotTextWidth(rotfont, str, strlen(str));
  2198. X
  2199. X   if(dir==1)
  2200. X     XFillRectangle(dpy, drawable, my_gc, x-rotfont->max_ascent+1, y-width,
  2201. X                    rotfont->height-1, width);
  2202. X   else if(dir==2)
  2203. X     XFillRectangle(dpy, drawable, my_gc, x-width, y-rotfont->max_descent+1,
  2204. X                    width, rotfont->height-1);
  2205. X   else
  2206. X     XFillRectangle(dpy, drawable, my_gc, x-rotfont->max_descent+1,
  2207. X                    y, rotfont->height-1, width);
  2208. X
  2209. X#ifndef X11R3
  2210. X   XSetForeground(dpy, my_gc, values.foreground);
  2211. X#endif
  2212. X  }
  2213. X
  2214. X XSetFillStyle(dpy, my_gc, FillStippled);
  2215. X
  2216. X /* loop through each character in string ... */
  2217. X for(i=0; i<len; i++)
  2218. X {
  2219. X  ichar=str[i]-32;
  2220. X
  2221. X  /* make sure it's a printing character ... */
  2222. X  if((ichar>=0)&&(ichar<95))
  2223. X  {
  2224. X   /* suitable offset ... */
  2225. X   if(dir==1)
  2226. X     { xp=x-rotfont->per_char[ichar].ascent;
  2227. X       yp=y-rotfont->per_char[ichar].rbearing; }
  2228. X   else if(dir==2)
  2229. X     { xp=x-rotfont->per_char[ichar].rbearing;
  2230. X       yp=y-rotfont->per_char[ichar].descent+1; }
  2231. X   else
  2232. X     { xp=x-rotfont->per_char[ichar].descent+1;  
  2233. X       yp=y+rotfont->per_char[ichar].lbearing; }
  2234. X                   
  2235. X   /* draw the glyph ... */
  2236. X   XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm);
  2237. X
  2238. X   XSetTSOrigin(dpy, my_gc, xp, yp);
  2239. X   
  2240. X   XFillRectangle(dpy, drawable, my_gc, xp, yp,
  2241. X                  rotfont->per_char[ichar].glyph.bit_w,
  2242. X                  rotfont->per_char[ichar].glyph.bit_h);
  2243. X    
  2244. X   /* advance position ... */
  2245. X   if(dir==1)      y-=rotfont->per_char[ichar].width;
  2246. X   else if(dir==2) x-=rotfont->per_char[ichar].width;
  2247. X   else            y+=rotfont->per_char[ichar].width;
  2248. X  }
  2249. X }
  2250. X}
  2251. X  
  2252. X    
  2253. X/* ---------------------------------------------------------------------- */
  2254. X
  2255. X
  2256. X/* *** A front end to XRotPaintAlignedString : uses XRotDrawString *** */
  2257. X
  2258. Xvoid XRotDrawAlignedString(dpy, drawable, rotfont, gc, x, y,
  2259. X                                  text, align)
  2260. X Display *dpy;                    
  2261. X Drawable drawable;
  2262. X XRotFontStruct *rotfont;
  2263. X GC gc;
  2264. X int x, y;
  2265. X char *text;
  2266. X int align;
  2267. X{
  2268. X XRotPaintAlignedString(dpy, drawable, rotfont, gc, x, y, text, align, 0);
  2269. X}
  2270. X
  2271. X
  2272. X/* ---------------------------------------------------------------------- */
  2273. X
  2274. X
  2275. X/* *** A front end to XRotPaintAlignedString : uses XRotDrawImageString *** */
  2276. X
  2277. Xvoid XRotDrawAlignedImageString(dpy, drawable, rotfont, gc, x, y,
  2278. X                                  text, align)
  2279. X Display *dpy;
  2280. X Drawable drawable;  
  2281. X XRotFontStruct *rotfont;
  2282. X GC gc;
  2283. X int x, y;
  2284. X char *text;
  2285. X int align;
  2286. X{
  2287. X XRotPaintAlignedString(dpy, drawable, rotfont, gc, x, y, text, align, 1);
  2288. X}
  2289. X
  2290. X
  2291. X/* ---------------------------------------------------------------------- */
  2292. X                   
  2293. X                   
  2294. X/* *** Routine to paint a string, possibly containing newline characters,
  2295. X                                                       with alignment *** */
  2296. X
  2297. X/* *** The user should use one of the front ends above *** */
  2298. X
  2299. Xvoid XRotPaintAlignedString(dpy, drawable, rotfont, gc, x, y, text,
  2300. X                            align, paintbg)
  2301. X Display *dpy;
  2302. X Drawable drawable;
  2303. X XRotFontStruct *rotfont;
  2304. X GC gc;
  2305. X int x, y;
  2306. X char *text;
  2307. X int align;
  2308. X int paintbg;
  2309. X{  
  2310. X int xp, yp, dir;
  2311. X int i, nl=1, max_width=0, this_width;
  2312. X char *str1, *str2="\n\0", *str3;
  2313. X
  2314. X if(text==NULL) return;
  2315. X  
  2316. X dir=rotfont->dir;
  2317. X
  2318. X /* count number of sections in string ... */
  2319. X for(i=0; i<strlen(text); i++) if(text[i]=='\n') nl++;
  2320. X
  2321. X /* find width of longest section ... */
  2322. X str1=my_strdup(text);
  2323. X str3=my_strtok(str1, str2);
  2324. X max_width=XRotTextWidth(rotfont, str3, strlen(str3));
  2325. X
  2326. X do
  2327. X  { str3=my_strtok((char *)NULL, str2);
  2328. X    if(str3)
  2329. X      max_width=XROTMAX(max_width,
  2330. X                        XRotTextWidth(rotfont, str3, strlen(str3))); }
  2331. X while(str3!=NULL);
  2332. X /* calculate vertical starting point according to alignment policy and
  2333. X      rotation angle ... */
  2334. X if(dir==0)
  2335. X { if((align==TLEFT)||(align==TCENTRE)||(align==TRIGHT))
  2336. X     yp=y+rotfont->max_ascent;
  2337. X
  2338. X  else if((align==BLEFT)||(align==BCENTRE)||(align==BRIGHT))
  2339. X     yp=y-(nl-1)*rotfont->height - rotfont->max_descent;
  2340. X
  2341. X  else 
  2342. X     yp=y-(nl-1)/2*rotfont->height + rotfont->max_ascent -rotfont->height/2 -
  2343. X                         ( (nl%2==0)?rotfont->height/2:0 ); }
  2344. X
  2345. X else if(dir==1)
  2346. X { if((align==TLEFT)||(align==TCENTRE)||(align==TRIGHT))
  2347. X     xp=x+rotfont->max_ascent;
  2348. X
  2349. X   else if((align==BLEFT)||(align==BCENTRE)||(align==BRIGHT))
  2350. X     xp=x-(nl-1)*rotfont->height - rotfont->max_descent;
  2351. X
  2352. X   else 
  2353. X     xp=x-(nl-1)/2*rotfont->height + rotfont->max_ascent -rotfont->height/2 -
  2354. X                         ( (nl%2==0)?rotfont->height/2:0 ); }
  2355. X
  2356. X else if(dir==2)
  2357. X { if((align==TLEFT)||(align==TCENTRE)||(align==TRIGHT))
  2358. X     yp=y-rotfont->max_ascent;
  2359. X     
  2360. X   else if((align==BLEFT)||(align==BCENTRE)||(align==BRIGHT))
  2361. X     yp=y+(nl-1)*rotfont->height + rotfont->max_descent;
  2362. X     
  2363. X   else 
  2364. X     yp=y+(nl-1)/2*rotfont->height - rotfont->max_ascent +rotfont->height/2 +
  2365. X                         ( (nl%2==0)?rotfont->height/2:0 ); }
  2366. X
  2367. X else
  2368. X { if((align==TLEFT)||(align==TCENTRE)||(align==TRIGHT))
  2369. X     xp=x-rotfont->max_ascent;
  2370. X    
  2371. X   else if((align==BLEFT)||(align==BCENTRE)||(align==BRIGHT))
  2372. X     xp=x+(nl-1)*rotfont->height + rotfont->max_descent;
  2373. X  
  2374. X   else 
  2375. X     xp=x+(nl-1)/2*rotfont->height - rotfont->max_ascent +rotfont->height/2 +
  2376. X                         ( (nl%2==0)?rotfont->height/2:0 ); }
  2377. X
  2378. X str1=my_strdup(text);
  2379. X str3=my_strtok(str1, str2);
  2380. X  
  2381. X /* loop through each section in the string ... */
  2382. X do
  2383. X {
  2384. X  /* width of this section ... */
  2385. X  this_width=XRotTextWidth(rotfont, str3, strlen(str3));
  2386. X
  2387. X  /* horizontal alignment ... */
  2388. X  if(dir==0)
  2389. X  { if((align==TLEFT)||(align==MLEFT)||(align==BLEFT))
  2390. X      xp=x;
  2391. X  
  2392. X    else if((align==TCENTRE)||(align==MCENTRE)||(align==BCENTRE))
  2393. X      xp=x-this_width/2;
  2394. X    else 
  2395. X      xp=x-max_width; }
  2396. X
  2397. X  else if(dir==1)
  2398. X  { if((align==TLEFT)||(align==MLEFT)||(align==BLEFT))
  2399. X      yp=y;
  2400. X
  2401. X    else if((align==TCENTRE)||(align==MCENTRE)||(align==BCENTRE))
  2402. X      yp=y+this_width/2;
  2403. X
  2404. X    else 
  2405. X      yp=y+max_width; }
  2406. X
  2407. X  else if(dir==2)
  2408. X  { if((align==TLEFT)||(align==MLEFT)||(align==BLEFT))
  2409. X      xp=x;
  2410. X  
  2411. X    else if((align==TCENTRE)||(align==MCENTRE)||(align==BCENTRE))
  2412. X      xp=x+this_width/2;
  2413. X    else 
  2414. X      xp=x+max_width; }
  2415. X
  2416. X  else
  2417. X  { if((align==TLEFT)||(align==MLEFT)||(align==BLEFT))  
  2418. X      yp=y;
  2419. X     
  2420. X    else if((align==TCENTRE)||(align==MCENTRE)||(align==BCENTRE))
  2421. X      yp=y-this_width/2;
  2422. X     
  2423. X    else 
  2424. X      yp=y-max_width; }
  2425. X
  2426. X  /* draw the section ... */
  2427. X  if(!paintbg)  XRotDrawString(dpy, drawable, rotfont, gc, xp, yp,
  2428. X                               str3, strlen(str3));
  2429. X  else          XRotDrawImageString(dpy, drawable, rotfont, gc, xp, yp, 
  2430. X                               str3, strlen(str3));  
  2431. X
  2432. X  str3=my_strtok((char *)NULL, str2);
  2433. X
  2434. X  /* advance position ... */
  2435. X  if(dir==0)      yp+=rotfont->height;
  2436. X  else if(dir==1) xp+=rotfont->height;
  2437. X  else if(dir==2) yp-=rotfont->height;
  2438. X  else            xp-=rotfont->height;
  2439. X }
  2440. X while(str3!=NULL);
  2441. X}
  2442. X
  2443. END_OF_FILE
  2444. if test 21004 -ne `wc -c <'w_rottext.c'`; then
  2445.     echo shar: \"'w_rottext.c'\" unpacked with wrong size!
  2446. fi
  2447. # end of 'w_rottext.c'
  2448. fi
  2449. echo shar: End of archive 14 \(of 27\).
  2450. cp /dev/null ark14isdone
  2451. MISSING=""
  2452. 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
  2453.     if test ! -f ark${I}isdone ; then
  2454.     MISSING="${MISSING} ${I}"
  2455.     fi
  2456. done
  2457. if test "${MISSING}" = "" ; then
  2458.     echo You have unpacked all 27 archives.
  2459.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2460. else
  2461.     echo You still need to unpack the following archives:
  2462.     echo "        " ${MISSING}
  2463. fi
  2464. ##  End of shell archive.
  2465. exit 0
  2466.  
  2467. exit 0 # Just in case...
  2468. -- 
  2469.   // chris@IMD.Sterling.COM       | Send comp.sources.x submissions to:
  2470. \X/  Amiga - The only way to fly! |    sources-x@imd.sterling.com
  2471.  "It's intuitively obvious to the |
  2472.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  2473.