home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xfig / part14 / d_text.c next >
Encoding:
C/C++ Source or Header  |  1993-05-27  |  20.7 KB  |  774 lines

  1. /*
  2.  * FIG : Facility for Interactive Generation of figures
  3.  * Copyright (c) 1985 by Supoj Sutanthavibul
  4.  * Copyright (c) 1992 by Brian V. Smith
  5.  * "Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both the copyright
  8.  * notice and this permission notice appear in supporting documentation. 
  9.  * No representations are made about the suitability of this software for 
  10.  * any purpose.  It is provided "as is" without express or implied warranty."
  11.  */
  12.  
  13. #include "fig.h"
  14. #include "resources.h"
  15. #include "mode.h"
  16. #include "object.h"
  17. #include "paintop.h"
  18. #include "u_create.h"
  19. #include "u_fonts.h"
  20. #include "u_list.h"
  21. #include "u_search.h"
  22. #include "w_canvas.h"
  23. #include "w_drawprim.h"
  24. #include "w_mousefun.h"
  25. #include "w_setup.h"
  26. #include "w_zoom.h"
  27.  
  28. extern PIX_ROT_FONT lookfont();
  29.  
  30. #define CTRL_H    8
  31. #define NL    10
  32. #define CR    13
  33. #define CTRL_X    24
  34. #define SP    32
  35. #define DEL    127
  36.  
  37. #define            BUF_SIZE    400
  38.  
  39. char        prefix[BUF_SIZE],    /* part of string left of mouse click */
  40.         suffix[BUF_SIZE];    /* part to right of click */
  41. int        leng_prefix, leng_suffix;
  42. static int    char_ht;
  43. static int    base_x, base_y;
  44. static PIX_ROT_FONT canvas_zoomed_font;
  45.  
  46. static int    work_psflag, work_font, work_fontsize, work_textjust;
  47. static PIX_ROT_FONT work_fontstruct;
  48. static float    work_angle;
  49. static        finish_n_start();
  50. static        init_text_input(), cancel_text_input();
  51. static        wrap_up();
  52. int        char_handler();
  53. static F_text  *new_text();
  54.  
  55. static int    cpy_n_char();
  56. static int    prefix_length();
  57. static int    initialize_char_handler();
  58. static int    terminate_char_handler();
  59. static int    erase_char_string();
  60. static int    draw_char_string();
  61. static int    turn_on_blinking_cursor();
  62. static int    turn_off_blinking_cursor();
  63. static int    move_blinking_cursor();
  64.  
  65. text_drawing_selected()
  66. {
  67.     canvas_kbd_proc = null_proc;
  68.     canvas_locmove_proc = null_proc;
  69.     canvas_middlebut_proc = null_proc;
  70.     canvas_leftbut_proc = init_text_input;
  71.     canvas_rightbut_proc = null_proc;
  72.     set_mousefun("posn cursor", "", "");
  73.     set_cursor(pencil_cursor);
  74. }
  75.  
  76. static
  77. finish_n_start(x, y)
  78. {
  79.     wrap_up();
  80.     init_text_input(x, y);
  81. }
  82.  
  83. finish_text_input()
  84. {
  85.     wrap_up();
  86.     text_drawing_selected();
  87.     draw_mousefun_canvas();
  88. }
  89.  
  90. static
  91. cancel_text_input()
  92. {
  93.     erase_char_string();
  94.     terminate_char_handler();
  95.     if (cur_t != NULL) {
  96.     draw_text(cur_t, PAINT);
  97.     toggle_textmarker(cur_t);
  98.     }
  99.     text_drawing_selected();
  100.     draw_mousefun_canvas();
  101.     reset_action_on();
  102. }
  103.  
  104. static
  105. new_text_line()
  106. {
  107.     wrap_up();
  108.     if (work_angle < 90.0 - 0.001) {
  109.     cur_y += (int) ((float) char_ht * cur_textstep);
  110.     cur_x = base_x;
  111.     } else if (work_angle < 180.0 - 0.001) {
  112.     cur_x += (int) ((float) char_ht * cur_textstep);
  113.     cur_y = base_y;
  114.     } else if (work_angle < 270.0 - 0.001) {
  115.     cur_y -= (int) ((float) char_ht * cur_textstep);
  116.     cur_x = base_x;
  117.     } else {
  118.     cur_x -= (int) ((float) char_ht * cur_textstep);
  119.     cur_y = base_y;
  120.     }
  121.     init_text_input(cur_x, cur_y);
  122. }
  123.  
  124. static
  125. wrap_up()
  126. {
  127.     PR_SIZE        size;
  128.  
  129.     reset_action_on();
  130.     erase_char_string();
  131.     terminate_char_handler();
  132.  
  133.     if (cur_t == NULL) {    /* a brand new text */
  134.     if (leng_prefix == 0)
  135.         return;
  136.     cur_t = new_text();
  137.     add_text(cur_t);
  138.     } else {            /* existing text modified */
  139.     strcat(prefix, suffix);
  140.     leng_prefix += leng_suffix;
  141.     if (leng_prefix == 0) {
  142.         delete_text(cur_t);
  143.         return;
  144.     }
  145.     if (!strcmp(cur_t->cstring, prefix)) {
  146.         /* we didn't change anything */
  147.         draw_text(cur_t, PAINT);
  148.         toggle_textmarker(cur_t);
  149.         return;
  150.     }
  151.     new_t = copy_text(cur_t);
  152.     change_text(cur_t, new_t);
  153.     if (strlen(new_t->cstring) >= leng_prefix) {
  154.         strcpy(new_t->cstring, prefix);
  155.     } else {        /* free old and allocate new */
  156.         free(new_t->cstring);
  157.         if ((new_t->cstring = new_string(leng_prefix + 1)) != NULL)
  158.         strcpy(new_t->cstring, prefix);
  159.     }
  160.     size = pf_textwidth(canvas_font, leng_prefix, prefix);
  161.     new_t->height = size.y;
  162.     new_t->length = size.x; /* in pixels */
  163.     cur_t = new_t;
  164.     }
  165.     draw_text(cur_t, PAINT);
  166.     mask_toggle_textmarker(cur_t);
  167. }
  168.  
  169. static
  170. init_text_input(x, y)
  171.     int            x, y;
  172. {
  173.     int            length, d;
  174.     PR_SIZE        tsize;
  175.  
  176.     cur_x = x;
  177.     cur_y = y;
  178.  
  179.     set_action_on();
  180.     set_mousefun("reposn cursor", "finish text", "cancel");
  181.     draw_mousefun_canvas();
  182.     canvas_kbd_proc = char_handler;
  183.     canvas_middlebut_proc = finish_text_input;
  184.     canvas_leftbut_proc = finish_n_start;
  185.     canvas_rightbut_proc = cancel_text_input;
  186.  
  187.     /*
  188.      * set working font info to current settings. This allows user to change
  189.      * font settings while we are in the middle of accepting text without
  190.      * affecting this text i.e. we don't allow the text to change midway
  191.      * through
  192.      */
  193.  
  194.     put_msg("Ready for text input (from keyboard)");
  195.     if ((cur_t = text_search(cur_x, cur_y)) == NULL) {    /* new text input */
  196.     leng_prefix = leng_suffix = 0;
  197.     *suffix = 0;
  198.     prefix[leng_prefix] = '\0';
  199.     base_x = cur_x;
  200.     base_y = cur_y;
  201.  
  202.     work_fontsize = cur_fontsize;
  203.     work_font     = using_ps ? cur_ps_font : cur_latex_font;
  204.     work_psflag   = using_ps;
  205.     work_textjust = cur_textjust;
  206.     work_angle    = cur_elltextangle;
  207.     if (work_angle < 0.0)
  208.         work_angle += 360.0;
  209.  
  210.     /* load the X font and get its id for this font, size and angle UNZOOMED */
  211.     /* this is to get widths etc for the unzoomed chars */
  212.     canvas_font = lookfont(x_fontnum(work_psflag, work_font), 
  213.                work_fontsize, work_angle*M_PI/180.0);
  214.     /* get the ZOOMED font for actually drawing on the canvas */
  215.     canvas_zoomed_font = lookfont(x_fontnum(work_psflag, work_font), 
  216.                round(work_fontsize*zoomscale), work_angle*M_PI/180.0);
  217.     /* save the working font structure */
  218.     work_fontstruct = canvas_zoomed_font;
  219.     } else {            /* clicked on existing text */
  220.     if (hidden_text(cur_t)) {
  221.         put_msg("Can't edit hidden text");
  222.         reset_action_on();
  223.         text_drawing_selected();
  224.         return;
  225.     }
  226.     /* update the working text parameters */
  227.     work_font = cur_t->font;
  228.     work_fontstruct = canvas_zoomed_font = cur_t->fontstruct;
  229.     work_fontsize = cur_t->size;
  230.     work_psflag   = cur_t->flags;
  231.     work_textjust = cur_t->type;
  232.     work_angle    = cur_t->angle*180.0/M_PI;
  233.     if (work_angle < 0.0)
  234.         work_angle += 360.0;
  235.     /* load the X font and get its id for this font, size and angle UNZOOMED */
  236.     /* this is to get widths etc for the unzoomed chars */
  237.     canvas_font = lookfont(x_fontnum(work_psflag, work_font), 
  238.                work_fontsize, work_angle*M_PI/180.0);
  239.  
  240.     toggle_textmarker(cur_t);
  241.     draw_text(cur_t, ERASE);
  242.     base_x = cur_t->base_x;
  243.     base_y = cur_t->base_y;
  244.     length = cur_t->length;
  245.     switch (cur_t->type) {
  246.     case T_CENTER_JUSTIFIED:
  247.         if (work_angle < 90.0 - 0.001) 
  248.         base_x -= length / 2;
  249.         else if (work_angle < 180.0 - 0.001)
  250.         base_y += length / 2;
  251.         else if (work_angle < 270.0 - 0.001)
  252.         base_x += length / 2;
  253.         else
  254.         base_y -= length / 2;
  255.         break;
  256.  
  257.     case T_RIGHT_JUSTIFIED:
  258.         if (work_angle < 90.0 - 0.001) 
  259.         base_x -= length;
  260.         else if (work_angle < 180.0 - 0.001)
  261.         base_y += length;
  262.         else if (work_angle < 270.0 - 0.001)
  263.         base_x += length;
  264.         else
  265.         base_y -= length;
  266.         break;
  267.     } /* switch */
  268.     if (work_angle < 90.0 - 0.001 || (work_angle >= 180.0 - 0.001 
  269.         && work_angle < 270.0 - 0.001))
  270.         d = abs(cur_x - base_x);
  271.     else
  272.         d = abs(cur_y - base_y);
  273.     leng_suffix = strlen(cur_t->cstring);
  274.     /* leng_prefix is # of char in the text before the cursor */
  275.     leng_prefix = prefix_length(cur_t->cstring, d);
  276.     leng_suffix -= leng_prefix;
  277.     cpy_n_char(prefix, cur_t->cstring, leng_prefix);
  278.     strcpy(suffix, &cur_t->cstring[leng_prefix]);
  279.     tsize = pf_textwidth(canvas_font, leng_prefix, prefix);
  280.  
  281.     if (work_angle < 90.0 - 0.001) {
  282.         cur_x = base_x + tsize.x;
  283.         cur_y = base_y;
  284.     } else if (work_angle < 180.0 - 0.001) {
  285.         cur_x = base_x;
  286.         cur_y = base_y - tsize.x;
  287.     } else if (work_angle < 270.0 - 0.001) {
  288.         cur_x = base_x - tsize.x;
  289.         cur_y = base_y;
  290.     } else {
  291.         cur_x = base_x;
  292.         cur_y = base_y + tsize.x;
  293.     }
  294.     }
  295.     char_ht = rot_char_height(canvas_font);
  296.     initialize_char_handler(canvas_win, finish_text_input,
  297.                 base_x, base_y);
  298.     draw_char_string();
  299. }
  300.  
  301. static
  302. F_text           *
  303. new_text()
  304. {
  305.     F_text       *text;
  306.     PR_SIZE        size;
  307.  
  308.     if ((text = create_text()) == NULL)
  309.     return (NULL);
  310.  
  311.     if ((text->cstring = new_string(leng_prefix + 1)) == NULL) {
  312.     free((char *) text);
  313.     return (NULL);
  314.     }
  315.     text->type = work_textjust;
  316.     text->font = work_font;    /* put in current font number */
  317.     text->fontstruct = work_fontstruct;
  318.     text->size = work_fontsize;
  319.     text->angle = work_angle/180.0*M_PI;    /* convert to radians */
  320.     text->flags = cur_textflags;
  321.     text->color = cur_color;
  322.     text->depth = cur_depth;
  323.     text->pen = 0;
  324.     size = pf_textwidth(canvas_font, leng_prefix, prefix);
  325.     text->length = size.x;    /* in pixels */
  326.     text->height = size.y;    /* in pixels */
  327.     text->base_x = base_x;
  328.     text->base_y = base_y;
  329.     strcpy(text->cstring, prefix);
  330.     text->next = NULL;
  331.     return (text);
  332. }
  333.  
  334. static int
  335. cpy_n_char(dst, src, n)
  336.     char       *dst, *src;
  337.     int            n;
  338. {
  339.     /* src must be longer than n chars */
  340.  
  341.     while (n--)
  342.     *dst++ = *src++;
  343.     *dst = '\0';
  344. }
  345.  
  346. static int
  347. prefix_length(string, where_p)
  348.     char       *string;
  349.     int            where_p;
  350. {
  351.     /* c stands for character unit and p for pixel unit */
  352.     int            l, len_c, len_p;
  353.     int            char_wid, where_c;
  354.     PR_SIZE        size;
  355.  
  356.     len_c = strlen(string);
  357.     size = pf_textwidth(canvas_font, len_c, string);
  358.     len_p = size.x;
  359.     if (where_p >= len_p)
  360.     return (len_c);        /* entire string is the prefix */
  361.  
  362.     char_wid = rot_char_width(canvas_font);
  363.     where_c = where_p / char_wid;    /* estimated char position */
  364.     size = pf_textwidth(canvas_font, where_c, string);
  365.     l = size.x;            /* actual length (pixels) of string of
  366.                  * where_c chars */
  367.     if (l < where_p) {
  368.     do {            /* add the width of next char to l */
  369.         l += (char_wid = rot_char_advance(canvas_font, 
  370.                 (unsigned char) string[where_c++]));
  371.     } while (l < where_p);
  372.     if (l - (char_wid >> 1) >= where_p)
  373.         where_c--;
  374.     } else if (l > where_p) {
  375.     do {            /* subtract the width of last char from l */
  376.         l -= (char_wid = rot_char_advance(canvas_font, 
  377.                 (unsigned char) string[--where_c]));
  378.     } while (l > where_p);
  379.     if (l + (char_wid >> 1) >= where_p)
  380.         where_c++;
  381.     }
  382.     if (where_c < 0) {
  383.     fprintf(stderr, "xfig file %s line %d: Error in prefix_length - adjusted\n", __FILE__, __LINE__);
  384.     where_c = 0;
  385.     }
  386.     return (where_c);
  387. }
  388.  
  389. /*******************************************************************
  390.  
  391.     char handling routines
  392.  
  393. *******************************************************************/
  394.  
  395. #define            BLINK_INTERVAL    700    /* milliseconds blink rate */
  396.  
  397. static Window    pw;
  398. static int    ch_height;
  399. static int    cbase_x, cbase_y;
  400. static float    rbase_x, rbase_y, rcur_x, rcur_y;
  401.  
  402. static        (*cr_proc) ();
  403.  
  404. static
  405. draw_cursor(x, y)
  406.     int            x, y;
  407. {
  408.     if (work_angle < 90.0 - 0.001)        /* 0-89 degrees */
  409.         pw_vector(pw, x, y, x, y-ch_height, INV_PAINT, 1, RUBBER_LINE, 0.0,
  410.         DEFAULT_COLOR);
  411.     else if (work_angle < 180.0 - 0.001)    /* 90-179 degrees */
  412.         pw_vector(pw, x-ch_height, y, x, y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  413.         DEFAULT_COLOR);
  414.     else if (work_angle < 270.0 - 0.001)    /* 180-269 degrees */
  415.         pw_vector(pw, x, y+ch_height, x, y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  416.         DEFAULT_COLOR);
  417.     else                /* 270-359 degrees */
  418.         pw_vector(pw, x, y, x+ch_height, y, INV_PAINT, 1, RUBBER_LINE, 0.0,
  419.         DEFAULT_COLOR);
  420. }
  421.  
  422. static int
  423. initialize_char_handler(p, cr, bx, by)
  424.     Window        p;
  425.     int            (*cr) ();
  426.     int            bx, by;
  427. {
  428.     pw = p;
  429.     cr_proc = cr;
  430.     rbase_x = cbase_x = bx;    /* keep real base so dont have roundoff */
  431.     rbase_y = cbase_y = by;
  432.     rcur_x = cur_x;
  433.     rcur_y = cur_y;
  434.  
  435.     ch_height = rot_char_height(canvas_font);
  436.     turn_on_blinking_cursor(draw_cursor, draw_cursor,
  437.                 cur_x, cur_y, (long) BLINK_INTERVAL);
  438. }
  439.  
  440. static int
  441. terminate_char_handler()
  442. {
  443.     turn_off_blinking_cursor();
  444.     cr_proc = NULL;
  445. }
  446.  
  447. /*
  448.  * we use INV_PAINT below instead of ERASE and PAINT to avoid interactions
  449.  * with the cursor.  It means that we need to do a ERASE before we start the
  450.  * cursor and a PAINT after it is turned off.
  451.  */
  452.  
  453. static int
  454. erase_char_string()
  455. {
  456.     pw_text(pw, cbase_x, cbase_y, INV_PAINT, canvas_zoomed_font, 
  457.         prefix, DEFAULT_COLOR);
  458.     if (leng_suffix)
  459.     pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  460.         suffix, DEFAULT_COLOR);
  461. }
  462.  
  463. static int
  464. draw_char_string()
  465. {
  466.     pw_text(pw, cbase_x, cbase_y, INV_PAINT, canvas_zoomed_font, 
  467.         prefix, DEFAULT_COLOR);
  468.     if (leng_suffix)
  469.     pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  470.         suffix, DEFAULT_COLOR);
  471.     move_blinking_cursor(cur_x, cur_y);
  472. }
  473.  
  474. static int
  475. draw_suffix()
  476. {
  477.     if (leng_suffix)
  478.     pw_text(pw, cur_x, cur_y, PAINT, canvas_zoomed_font, 
  479.         suffix, DEFAULT_COLOR);
  480. }
  481.  
  482. static int
  483. erase_suffix()
  484. {
  485.     if (leng_suffix)
  486.     pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  487.         suffix, DEFAULT_COLOR);
  488. }
  489.  
  490. static int
  491. draw_char(c)
  492. char    c;
  493. {
  494.     char    s[2];
  495.     s[0]=c;
  496.     s[1]='\0';
  497.     pw_text(pw, cur_x, cur_y, INV_PAINT, canvas_zoomed_font, 
  498.         s, DEFAULT_COLOR);
  499. }
  500.  
  501. char_handler(c)
  502.     unsigned char   c;
  503. {
  504.     float        cwidth, cw2;
  505.  
  506.     if (cr_proc == NULL)
  507.     return;
  508.  
  509.     if (c == CR || c == NL) {
  510.     new_text_line();
  511.     } else if (c == DEL || c == CTRL_H) {
  512.     if (leng_prefix > 0) {
  513.         erase_char_string();
  514.         cwidth = (float) rot_char_advance(canvas_font, 
  515.             (unsigned char) prefix[leng_prefix - 1]);
  516.         cw2 = cwidth/2.0;
  517.         /* correct text/cursor posn for justification and zoom factor */
  518.         switch (work_textjust) {
  519.         case T_LEFT_JUSTIFIED:
  520.         if (work_angle < 90.0 - 0.001)
  521.             rcur_x -= cwidth;           /* 0-89 deg, move the suffix left */
  522.         else if (work_angle < 180.0 - 0.001) 
  523.             rcur_y += cwidth;           /* 90-179 deg, move suffix down */
  524.         else if (work_angle < 270.0 - 0.001) 
  525.             rcur_x += cwidth;           /* 180-269 deg, move suffix right */
  526.         else 
  527.             rcur_y -= cwidth;           /* 270-359 deg, move suffix up */
  528.         break;
  529.         case T_CENTER_JUSTIFIED:
  530.         if (work_angle < 90.0 - 0.001) { 
  531.             rbase_x += cw2;    /* 0-89 deg, move base right cw/2 */
  532.             rcur_x -= cw2;    /* move suffix left by cw/2 */
  533.         } else if (work_angle < 180.0 - 0.001) { 
  534.             rbase_y -= cw2;    /* 90-179 deg, move base up cw/2 */
  535.             rcur_y += cw2;    /* move suffix down cw/2 */
  536.         } else if (work_angle < 270.0 - 0.001) {
  537.             rbase_x -= cw2;    /* 180-269 deg, move base left cw/2 */
  538.             rcur_x += cw2;    /* move suffix right cw/2 */
  539.         } else {                      
  540.             rbase_y += cw2;    /* 270-359 deg, move base down cw/2 */
  541.             rcur_y -= cw2;    /* move suffix up cw/2 */
  542.         }
  543.         break;
  544.         case T_RIGHT_JUSTIFIED:
  545.         if (work_angle < 90.0 - 0.001) 
  546.             rbase_x += cwidth;           /* 0-89 deg, move the prefix right */
  547.         else if (work_angle < 180.0 - 0.001)
  548.             rbase_y -= cwidth;           /* 90-179 deg, move prefix up */
  549.         else if (work_angle < 270.0 - 0.001)
  550.             rbase_x -= cwidth;           /* 180-269 deg, move prefix left */
  551.         else
  552.             rbase_y += cwidth;           /* 270-359 deg, move prefix down */
  553.         break;
  554.         }
  555.         prefix[--leng_prefix] = '\0';
  556.         cbase_x = rbase_x;    /* fix */
  557.         cbase_y = rbase_y;
  558.         cur_x = rcur_x;
  559.         cur_y = rcur_y;
  560.         draw_char_string();
  561.     }
  562.     } else if (c == CTRL_X) {
  563.     if (leng_prefix > 0) {
  564.         erase_char_string();
  565.         switch (work_textjust) {
  566.         case T_CENTER_JUSTIFIED:
  567.         while (leng_prefix--)    /* subtract char width/2 per char */
  568.             if (work_angle < 90.0 - 0.001)    /* 0-89 degrees */
  569.             rcur_x -= rot_char_advance(canvas_font, 
  570.                 (unsigned char) prefix[leng_prefix]) / 2.0;
  571.         else if (work_angle < 180.0 - 0.001)     /* 90-179 degrees */
  572.             rcur_y += rot_char_advance(canvas_font, 
  573.                 (unsigned char) prefix[leng_prefix]) / 2.0;
  574.         else if (work_angle < 270.0 - 0.001)     /* 180-269 degrees */
  575.             rcur_x += rot_char_advance(canvas_font, 
  576.                 (unsigned char) prefix[leng_prefix]) / 2.0;
  577.         else                     /* 270-359 degrees */
  578.             rcur_y -= rot_char_advance(canvas_font, 
  579.                 (unsigned char) prefix[leng_prefix]) / 2.0;
  580.         cur_x = cbase_x = rbase_x = rcur_x;
  581.         cur_y = cbase_y = rbase_y = rcur_y;
  582.         break;
  583.         case T_RIGHT_JUSTIFIED:
  584.         cbase_x = rbase_x = cur_x = rcur_x;
  585.         cbase_y = rbase_y = cur_y = rcur_y;
  586.         break;
  587.         case T_LEFT_JUSTIFIED:
  588.         cur_x = rcur_x = cbase_x = rbase_x;
  589.         cur_y = rcur_y = cbase_y = rbase_y;
  590.         break;
  591.         }
  592.         leng_prefix = 0;
  593.         *prefix = '\0';
  594.         draw_char_string();
  595.     }
  596.     } else if (c < SP) {
  597.     put_msg("Invalid character ignored");
  598.     } else if (leng_prefix + leng_suffix == BUF_SIZE) {
  599.     put_msg("Text buffer is full, character is ignored");
  600.  
  601.     /* normal text character */
  602.     } else {    
  603.     draw_char_string();
  604.     cwidth = rot_char_advance(canvas_font, (unsigned char) c);
  605.     cw2 = cwidth/2.0;
  606.     /* correct text/cursor posn for justification and zoom factor */
  607.     switch (work_textjust) {
  608.       case T_LEFT_JUSTIFIED:
  609.         if (work_angle < 90.0 - 0.001)
  610.         rcur_x += cwidth;           /* 0-89 deg, move the suffix right */
  611.         else if (work_angle < 180.0 - 0.001) 
  612.         rcur_y -= cwidth;           /* 90-179 deg, move suffix up */
  613.         else if (work_angle < 270.0 - 0.001) 
  614.         rcur_x -= cwidth;           /* 180-269 deg, move suffix left */
  615.         else 
  616.         rcur_y += cwidth;           /* 270-359 deg, move suffix down */
  617.         break;
  618.       case T_CENTER_JUSTIFIED:
  619.         if (work_angle < 90.0 - 0.001) { 
  620.         rbase_x -= cw2;    /* 0-89 deg, move base left cw/2 */
  621.         rcur_x += cw2;    /* move suffix right by cw/2 */
  622.         } else if (work_angle < 180.0 - 0.001) { 
  623.         rbase_y += cw2;    /* 90-179 deg, move base down cw/2 */
  624.         rcur_y -= cw2;    /* move suffix up cw/2 */
  625.         } else if (work_angle < 270.0 - 0.001) {
  626.         rbase_x += cw2;    /* 180-269 deg, move base right cw/2 */
  627.         rcur_x -= cw2;    /* move suffix left cw/2 */
  628.         } else {                      
  629.         rbase_y -= cw2;    /* 270-359 deg, move base up cw/2 */
  630.         rcur_y += cw2;    /* move suffix down cw/2 */
  631.         }
  632.         break;
  633.       case T_RIGHT_JUSTIFIED:
  634.         if (work_angle < 90.0 - 0.001) 
  635.         rbase_x -= cwidth;           /* 0-89 deg, move the prefix left */
  636.         else if (work_angle < 180.0 - 0.001)
  637.         rbase_y += cwidth;           /* 90-179 deg, move prefix down */
  638.         else if (work_angle < 270.0 - 0.001)
  639.         rbase_x += cwidth;           /* 180-269 deg, move prefix right */
  640.         else
  641.         rbase_y -= cwidth;           /* 270-359 deg, move prefix up */
  642.         break;
  643.     }
  644.     prefix[leng_prefix++] = c;
  645.     prefix[leng_prefix] = '\0';
  646.     cbase_x = rbase_x;
  647.     cbase_y = rbase_y;
  648.     cur_x = rcur_x;
  649.     cur_y = rcur_y;
  650.     draw_char_string();
  651.     }
  652. }
  653.  
  654. /*******************************************************************
  655.  
  656.     blinking cursor handling routines
  657.  
  658. *******************************************************************/
  659.  
  660. static int    cursor_on, cursor_is_moving;
  661. static int    cursor_x, cursor_y;
  662. static int    (*erase) ();
  663. static int    (*draw) ();
  664. static XtTimerCallbackProc blink();
  665. static unsigned long blink_timer;
  666. static XtIntervalId blinkid;
  667. static int    stop_blinking = False;
  668. static int    cur_is_blinking = False;
  669.  
  670. static int
  671. turn_on_blinking_cursor(draw_cursor, erase_cursor, x, y, msec)
  672.     int            (*draw_cursor) ();
  673.     int            (*erase_cursor) ();
  674.     int            x, y;
  675.     unsigned long   msec;
  676. {
  677.     draw = draw_cursor;
  678.     erase = erase_cursor;
  679.     cursor_is_moving = 0;
  680.     cursor_x = x;
  681.     cursor_y = y;
  682.     blink_timer = msec;
  683.     draw(x, y);
  684.     cursor_on = 1;
  685.     if (!cur_is_blinking) {    /* if we are already blinking, don't request
  686.                  * another */
  687.     blinkid = XtAppAddTimeOut(tool_app, blink_timer, (XtTimerCallbackProc) blink,
  688.                   (XtPointer) NULL);
  689.     cur_is_blinking = True;
  690.     }
  691.     stop_blinking = False;
  692. }
  693.  
  694. static int
  695. turn_off_blinking_cursor()
  696. {
  697.     if (cursor_on)
  698.     erase(cursor_x, cursor_y);
  699.     stop_blinking = True;
  700. }
  701.  
  702. static        XtTimerCallbackProc
  703. blink(client_data, id)
  704.     XtPointer        client_data;
  705.     XtIntervalId   *id;
  706. {
  707.     if (!stop_blinking) {
  708.     if (cursor_is_moving)
  709.         return (0);
  710.     if (cursor_on) {
  711.         erase(cursor_x, cursor_y);
  712.         cursor_on = 0;
  713.     } else {
  714.         draw(cursor_x, cursor_y);
  715.         cursor_on = 1;
  716.     }
  717.     blinkid = XtAppAddTimeOut(tool_app, blink_timer, (XtTimerCallbackProc) blink,
  718.                   (XtPointer) NULL);
  719.     } else {
  720.     stop_blinking = False;    /* signal that we've stopped */
  721.     cur_is_blinking = False;
  722.     }
  723.     return (0);
  724. }
  725.  
  726. static int
  727. move_blinking_cursor(x, y)
  728.     int            x, y;
  729. {
  730.     cursor_is_moving = 1;
  731.     if (cursor_on)
  732.     erase(cursor_x, cursor_y);
  733.     cursor_x = x;
  734.     cursor_y = y;
  735.     draw(cursor_x, cursor_y);
  736.     cursor_on = 1;
  737.     cursor_is_moving = 0;
  738. }
  739.  
  740. reload_text_fstructs()
  741. {
  742.     F_text       *t;
  743.  
  744.     /* reload the compound objects' texts */
  745.     reload_compoundfont(objects.compounds);
  746.     /* and the separate texts */
  747.     for (t=objects.texts; t != NULL; t = t->next)
  748.     reload_text_fstruct(t);
  749. }
  750.  
  751. /*
  752.  * Reload the font structure for texts in compounds.
  753.  */
  754.  
  755. reload_compoundfont(compounds)
  756.     F_compound       *compounds;
  757. {
  758.     F_compound       *c;
  759.     F_text       *t;
  760.  
  761.     for (c = compounds; c != NULL; c = c->next) {
  762.     reload_compoundfont(c->compounds);
  763.     for (t=c->texts; t != NULL; t = t->next)
  764.         reload_text_fstruct(t);
  765.     }
  766. }
  767.  
  768. reload_text_fstruct(t)
  769.     F_text       *t;
  770. {
  771.     t->fontstruct = lookfont(x_fontnum(t->flags, t->font), 
  772.             round(t->size*zoomscale), t->angle);
  773. }
  774.