home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / csrtext.c < prev    next >
C/C++ Source or Header  |  1991-01-18  |  14KB  |  465 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    CrsrText.c (CursorText)
  6.  * Purpose:    Initialize and change states of the software cursor
  7.  * Subroutine:    init_textcursor()        returns: void
  8.  * Subroutine:    new_textcursor()        returns: void
  9.  * Subroutine:    draw_textcursor()        returns: void
  10.  * Subroutine:    reset_textcursor_coords()    returns: void
  11.  * Subroutine:    move_textcursor()        returns: void
  12.  * Subroutine:    textcursor_keyentry()        returns: void
  13.  * Subroutine:    reload_textcursor()        returns: void
  14.  * Subroutine:    save_textcursor()        returns: void
  15.  * Copyright:    1990 Michael VanHilst
  16.  *        You may do anything you like with this file except remove
  17.  *        this copyright.  Michael VanHilst makes no representations
  18.  *        about the suitability of this software for any purpose.
  19.  *        It is provided "as is" without express or implied warranty.
  20.  * Modified:    {0} Michael VanHilst    initial version           1 Jan 1991
  21.  *        {n} <who> -- <does what> -- <when>
  22.  */
  23.  
  24. #ifndef VMS
  25. #ifdef SYSV
  26. #include <string.h>        /*  strlen, strcat, strcpy, strrchr  */
  27. #else
  28. #include <strings.h>        /*  strlen, strcat, strcpy, rindex  */
  29. #endif
  30. #else
  31. #include <string.h>        /*  strlen, strcat, strcpy, strrchr  */
  32. #endif
  33.  
  34. #include <stdio.h>        /*  stderr, NULL, etc.  */
  35. #include <X11/Xlib.h>        /*  X window stuff  */
  36. #include <X11/Xutil.h>        /*  X window manager stuff  */
  37. #include <X11/keysym.h>
  38. #include <X11/keysymdef.h>
  39. #include "hfiles/constant.h"    /*  Define codes  */
  40. #include "hfiles/struct.h"    /*  Declare structure types  */
  41. #include "hfiles/extern.h"    /*  Extern main parameter structures  */
  42. #include "hfiles/define.h"    /*  Define DONT_CARE, U_DONT_CARE  */
  43. #include "hfiles/edit.h"
  44. #include "hfiles/region.h"    /*  regdrawRec region drawing parameters  */
  45.  
  46. struct regdrawRec rgdraw;
  47.  
  48. /*  Ammount of space for string is actually (CURSOR_MAX - 1)*sizeof(XPoint)  */
  49. struct curText {
  50.   int char_cnt;
  51.   char string[CURSOR_MAX*2];
  52. };
  53.  
  54. static EditStruct *cursor_edit;
  55. static XFontStruct *fontstruct;
  56. static int init = 1;
  57.  
  58.  
  59. #ifdef ANSIC
  60. /*  Exported declarations must be centralized before ANSI C can be used  */
  61.  
  62. void        new_textcursor();
  63. void        clear_textcursor();
  64. void        save_textcursor(        XButtonEvent *xbutton);
  65. void        reload_textcursor();
  66. void        textcursor_keyentry(    XKeyEvent *xkey, KeySym keysym);
  67. void        draw_textcursor(        struct cursorRec *crsr, GCspec *draw);
  68. void        reset_textcursor_coords(    struct cursorRec *crsr);
  69. void        move_textcursor(        int xinc, int yinc);
  70. static void init_textcursor();
  71. static void draw_text_cursor_cursor(    EditStruct *edit, GC gc);
  72. static void clear_text_area(        EditStruct *edit,
  73.                     int x, int y, int width, int height);
  74. static void blacken_textcursor_cursor(    EditStruct *edit, int cur_x);
  75. void        write_text_region(        struct cursorRec *region, char* line);
  76.  
  77. #else
  78.  
  79.   XFontStruct *get_fontstruct();
  80.   EditStruct *get_edit_struct();
  81.   void init_edit_struct(), grab_keys_for_textcursor();
  82.   void grab_keys_for_textcursor(), clear_edit_buf();
  83.   void set_cursor_file_coords(), save_cursor_as_region(), disp_region();
  84.   void store_edit_struct();
  85.   void load_edit_string(), reset_textcursor_coords();
  86.   void set_edit_draw_func(), unset_edit_draw_func();
  87.   int emacs_response();
  88.   GC set_text_gc();
  89.   void draw_textcursor();
  90.   static void init_textcursor(), draw_textcursor_cursor();
  91.   static void clear_text_area(), blacken_textcursor_cursor();
  92.  
  93. #endif
  94.  
  95.  
  96. /*  Subroutine:    init_textcursor
  97.  *  Purpose:    initialize editor parameters for text cursor editing
  98.  */
  99. static void init_textcursor()
  100. {
  101.   /*  Get same font used for region labels  */
  102.   fontstruct = get_fontstruct(1);
  103.   /*  Allocate text editor struct space  */
  104.   cursor_edit = get_edit_struct((CURSOR_MAX-1)*4);
  105.   /*  Initialize text editor parameters  */
  106.   init_edit_struct(dispbox.display, dispbox.ID, cursor_edit, fontstruct,
  107.            cursor.draw->foreground, cursor.draw->background);
  108.   cursor_edit->y = cursor.win.y;
  109.   cursor_edit->x = cursor.win.x;
  110.   cursor_edit->max_pixlen = 512;
  111.   cursor_edit->area_y =
  112.     cursor_edit->y - cursor_edit->fontstruct->max_bounds.ascent;
  113.   /*  Set this value initially so position cursor will appear  */
  114.   cursor_edit->pixlen[1] = XTextWidth(cursor_edit->fontstruct, "e", 1);
  115. }
  116.  
  117.  
  118. /*  Subroutine:    new_textcursor()
  119.  *  Purpose:    set up cursor struct for text cursor interactions
  120.  */
  121. void new_textcursor()
  122. {
  123.   struct curText *curtext;
  124.  
  125.   if( init ) {
  126.     init_textcursor();
  127.     init = 0;
  128.   }
  129.   curtext = (struct curText *)cursor.points;
  130.   curtext->char_cnt = 0;
  131.   curtext->string[0] = '\0';
  132.   cursor.point_cnt = 2;
  133.   grab_keys_for_textcursor(1);
  134. }
  135.  
  136.  
  137. /*  Subroutine:    clear_textcursor
  138.  *  Purpose:    empty text cursor buffer and ungrab keyboard input
  139.  */
  140. void clear_textcursor()
  141. {
  142.   grab_keys_for_textcursor(0);
  143.   clear_edit_buf(cursor_edit);
  144. }
  145.  
  146.  
  147. /*  Subroutine:    save_textcursor
  148.  *  Purpose:    save string in editor on region save event
  149.  */
  150. #ifdef ANSIC
  151. void save_textcursor ( XButtonEvent *xbutton )
  152. #else
  153. void save_textcursor ( xbutton )
  154.      XButtonEvent *xbutton;
  155. #endif
  156. {
  157.   struct curText *curtext;
  158.  
  159.   /*  Force file coordinates into agreement with window coordinates  */
  160.   set_cursor_file_coords(&cursor, &coord.disptofile, 1);
  161.   /*  Save cursor as a region  */
  162.   if( xbutton->button == Button2 )
  163.     save_cursor_as_region(&cursor, 1);
  164.   else
  165.     save_cursor_as_region(&cursor, 0);
  166.   cursor.index = cursor.next_region->index;
  167.   disp_region(cursor.next_region);
  168.   store_edit_struct(cursor_edit);
  169.   curtext = (struct curText *)cursor.next_region->points;
  170.   --(curtext->char_cnt);
  171.   curtext->string[curtext->char_cnt] = '\0';
  172. }
  173.  
  174.  
  175. /*  Subroutine:    reload_textcursor
  176.  *  Purpose:    Put cursor string into editor buffer
  177.  */
  178. void reload_textcursor()
  179. {
  180.   struct curText *curtext;
  181.  
  182.   curtext = (struct curText *)cursor.points;
  183.   load_edit_string(cursor_edit, curtext->string, curtext->char_cnt);
  184.   reset_textcursor_coords(&cursor);
  185. }
  186.  
  187.  
  188. /*  Subroutine:    textcursor_keyentry
  189.  *  Purpose:    Respond to key entry while in textcursor mode
  190.  */
  191. #ifdef ANSIC
  192. void textcursor_keyentry ( XKeyEvent *xkey, KeySym keysym )
  193. #else
  194. void textcursor_keyentry ( xkey, keysym )
  195.      XKeyEvent *xkey;
  196.      KeySym keysym;
  197. #endif
  198. {
  199.   struct curText *curtext;
  200.   int old_end_x, old_cur_x;
  201.  
  202.   /*  Always use latest func, mask, and background  */
  203.   if( cursor.draw->mask != AllPlanes ) {
  204.     old_end_x = 0;
  205.     old_cur_x = -1;
  206.     draw_textcursor(&cursor, &color.gcset.undraw);
  207.   } else {
  208.     old_end_x = cursor_edit->pixlen[cursor_edit->char_cnt];
  209.     old_cur_x = cursor_edit->pixlen[cursor_edit->active_position];
  210.   }
  211.   /*  Intercept Linefeed so editor won't act on it  */
  212.   if( (keysym == XK_Linefeed) || (keysym == XK_Return) ) {
  213.     /*  Do a save and move cursor for next line on a carriage return  */
  214.     if( keysym == XK_Return )
  215.       ascii_region(&control.event.xkey, XK_s);
  216.     else
  217.       ascii_region(&control.event.xkey, XK_e);
  218.     /*  Move line done hight of text and set float coordinate as well  */
  219.     if( (cursor.win.y += cursor_edit->area_height) < 0 )
  220.       cursor.win.Y = (double)cursor.win.y - 0.5;
  221.     else
  222.       cursor.win.Y = (double)cursor.win.y + 0.5;
  223.     curtext = (struct curText *)cursor.points;
  224.     curtext->string[0] = '\0';
  225.     curtext->string[1] = '\0';
  226.     curtext->char_cnt = 0;
  227.     cursor.point_cnt = 2;
  228.     load_edit_string(cursor_edit, curtext->string, 0);
  229.     cursor_edit->active_position = 0;
  230.     reset_textcursor_coords(&cursor);
  231.     /*  Redraw the display window to clean things up and show new positions  */
  232.     disp_dispbox();
  233.     return;
  234.   } else {
  235.     /*  Suppress drawing by the editor (we do it here)  */
  236.     set_edit_draw_func(cursor.draw->func, 0);
  237.     (void)emacs_response(xkey, cursor_edit);
  238.     /*  Update cursor string to account for changes (incl. space on end)  */
  239.     curtext = (struct curText *)cursor.points;
  240. #ifdef ANSIC
  241.     (void)strncpy(curtext->string, cursor_edit->string,
  242.           (size_t)(cursor_edit->char_cnt + 1));
  243. #else
  244.     strncpy(curtext->string, cursor_edit->string, cursor_edit->char_cnt + 1);
  245. #endif
  246.     curtext->string[cursor_edit->char_cnt + 1] = '\0';
  247.     curtext->char_cnt = cursor_edit->char_cnt;
  248.     /*  Restore the default editor string drawing functions  */
  249.     unset_edit_draw_func();
  250.   }
  251.   /*  Use point count to reserve space for one byte more than string  */
  252.   /*  Point count is used by save cursor to copy bytes to region record  */
  253.   cursor.point_cnt = ((curtext->char_cnt + 1) / sizeof(XPoint)) + 2;
  254.   /*  If string got shorter and not erasing, blank stuff no longer covered  */
  255.   if( old_end_x > cursor_edit->pixlen[cursor_edit->char_cnt] ) {
  256.     int new_end_x;
  257.     GC gc;
  258.  
  259.     new_end_x = cursor_edit->pixlen[cursor_edit->char_cnt];
  260.     clear_text_area(cursor_edit, cursor_edit->x + new_end_x,
  261.             cursor_edit->y
  262.              - cursor_edit->fontstruct->max_bounds.ascent,
  263.             old_end_x - new_end_x,
  264.             cursor_edit->area_height);
  265.   }
  266.   /*  If cursor was or will not be erased, set it to background color  */
  267.   if( old_cur_x >= old_end_x )
  268.     blacken_textcursor_cursor(cursor_edit, old_cur_x);
  269.   /*  Draw new string  */
  270.   draw_textcursor(&cursor, cursor.draw);
  271. }
  272.  
  273.  
  274. /*  Subroutine:    draw_textcursor
  275.  *  Purpose:    draw a cursor, using only cursorRec info
  276.  */
  277. #ifdef ANSIC
  278. void draw_textcursor ( struct cursorRec *crsr, GCspec *draw )
  279. #else
  280. void draw_textcursor ( crsr, draw )
  281.      struct cursorRec *crsr;
  282.      GCspec *draw;
  283. #endif
  284. {
  285.   struct curText *curtext;
  286.   GC gc;
  287.  
  288.  
  289.   curtext = (struct curText *)crsr->points;
  290.   if( draw == NULL )
  291.     draw = crsr->draw;
  292.   /*  Make sure info is available  */
  293.   if( init ) {
  294.     init_textcursor();
  295.     init = 0;
  296.   }
  297.   /*  Stencil chars if tracking the string or not having a background  */
  298.   if( (draw->func == GXxor) ||
  299.       (draw->mask != AllPlanes) ) {
  300.     gc = set_text_gc(cursor_edit->font, draw->foreground, U_DONT_CARE,
  301.              draw->func, draw->mask);
  302.     XDrawString(crsr->win.display, crsr->win.ID, gc, crsr->win.x,
  303.         crsr->win.y, curtext->string, curtext->char_cnt);
  304.     if( crsr == &cursor ) {
  305.       /*  Update coords (cursor may have been moved in non-text mode)  */
  306.       cursor_edit->x = cursor.win.x;
  307.       cursor_edit->y = cursor.win.y;
  308.       draw_textcursor_cursor(cursor_edit, gc);
  309.     }
  310.   } else {
  311.     unsigned long foreground, background; /*  Text and background colors */
  312.  
  313.     /*  These backgrounds don't work with overlays, should use image dark  */
  314.     foreground = draw->foreground;
  315.     if( draw == &color.gcset.incl ) {
  316.       /*  Include is ALWAYS yellow or white on black  */
  317.       background = color.hard.true_black;
  318.       /*  This must be keyed to what disppsct.c does for hardcopy  */
  319.       if( foreground == color.hard.std_black )
  320.     foreground == color.hard.true_white;
  321.     } else if( draw == &color.gcset.excl ) {
  322.       /*  Exclude is ALWAYS red or black on white  */
  323.       background = color.hard.true_white;
  324.       /*  This must be keyed to what disppsct.c does for hardcopy  */
  325.       if( foreground == color.hard.std_white )
  326.     foreground = color.hard.true_black;
  327.     } else if( draw->foreground == color.hard.true_black )
  328.       background = color.hard.true_white;
  329.     else
  330.       background = color.hard.true_black;
  331.     gc = set_text_gc(cursor_edit->font, foreground, background,
  332.              draw->func, draw->mask);
  333.     XDrawImageString(cursor_edit->display, cursor_edit->ID, gc, crsr->win.x,
  334.              crsr->win.y, curtext->string, curtext->char_cnt);
  335.     if( crsr == &cursor ) {
  336.       cursor_edit->background = background;
  337.       /*  Update coords (cursor may have been moved in non-text mode)  */
  338.       cursor_edit->x = cursor.win.x;
  339.       cursor_edit->y = cursor.win.y;
  340.       draw_textcursor_cursor(cursor_edit, gc);
  341.     }
  342.   }
  343. }
  344.  
  345.  
  346. /*  Subroutine:    draw_textcursor_cursor
  347.  *  Xlib calls:    XDrawImageString()
  348.  */
  349. #ifdef ANSIC
  350. static void draw_textcursor_cursor ( EditStruct *edit, GC gc )
  351. #else
  352. static void draw_textcursor_cursor ( edit, gc )
  353.      EditStruct *edit;
  354.      GC gc;
  355. #endif
  356. {
  357.   int x;
  358.  
  359.   x = edit->x + edit->pixlen[edit->active_position] -
  360.     edit->pixlen[edit->first_char_shown];
  361.   XDrawLine(edit->display, edit->ID, gc, x, edit->y + 1,
  362.         x + edit->pixlen[1] - 1, edit->y + 1);
  363. }
  364.  
  365.  
  366. /*  Subroutine:    reset_textcursor_coords
  367.  */
  368. #ifdef ANSIC
  369. void reset_textcursor_coords( struct cursorRec *crsr )
  370. #else
  371. void reset_textcursor_coords( crsr )
  372.      struct cursorRec *crsr;
  373. #endif
  374. {
  375.   if( crsr == &cursor ) {
  376.     cursor_edit->x = cursor.win.x;
  377.     cursor_edit->y = cursor.win.y;
  378.     cursor_edit->area_y =
  379.       cursor_edit->y - cursor_edit->fontstruct->max_bounds.ascent;
  380.     cursor_edit->active_position = cursor_edit->char_cnt;
  381.   }
  382. }
  383.  
  384.  
  385. /*  Subroutine:    move_textcursor
  386.  *  Purpose:    Move the text drawing coords when text cursor is moved
  387.  */
  388. #ifdef ANSIC
  389. void move_textcursor ( int xinc, int yinc )
  390. #else
  391. void move_textcursor ( xinc, yinc )
  392.      int xinc, yinc;
  393. #endif
  394. {
  395.   cursor_edit->x += xinc;
  396.   cursor_edit->y += yinc;
  397.   cursor_edit->area_y += yinc;
  398. }
  399.  
  400.  
  401. /*  Subroutine:    clear_text_area
  402.  *  Purpose:    Clear area around edit string, mindful of mask in use
  403.  *  Note:    Assumes only called with GXcopy, AllPlanes, ImageString cursor
  404.  */
  405. #ifdef ANSIC
  406. static void clear_text_area ( EditStruct *edit,
  407.                   int x, int y, int width, int height )
  408. #else
  409. static void clear_text_area ( edit, x, y, width, height )
  410.      EditStruct *edit;
  411.      int x, y, width, height;
  412. #endif
  413. {
  414.   GC gc;
  415.  
  416.   gc = set_text_gc(edit->font, edit->background, U_DONT_CARE,
  417.            GXcopy, AllPlanes);
  418.   XFillRectangle(edit->display, edit->ID, gc, x, y,
  419.          (unsigned int)width, (unsigned int)height);
  420. }
  421.  
  422.  
  423. /*  Subroutine:    blacken_textcursor_cursor
  424.  *  Xlib calls:    XDrawImageString()
  425.  */
  426. #ifdef ANSIC
  427. static void blacken_textcursor_cursor ( EditStruct *edit, int cur_x )
  428. #else
  429. static void blacken_textcursor_cursor ( edit, cur_x )
  430.      EditStruct *edit;
  431.      int cur_x;
  432. #endif
  433. {
  434.   int x;
  435.   GC gc;
  436.  
  437.   gc = set_text_gc(edit->font, edit->background, U_DONT_CARE,
  438.            GXcopy, AllPlanes);
  439.   x = edit->x + cur_x - edit->pixlen[edit->first_char_shown];
  440.   XDrawLine(edit->display, edit->ID, gc, x, edit->y + 1,
  441.         x + edit->pixlen[1] - 1, edit->y + 1);
  442. }
  443.  
  444.  
  445. /*  Subroutine:    write_text_region
  446.  *  Purpose:    Write detail part of region file line for a text cursor
  447.  */
  448. #ifdef ANSIC
  449. void write_text_region ( struct cursorRec *region, char* line )
  450. #else
  451. void write_text_region ( region, line )
  452.      struct cursorRec *region;
  453.      char* line;
  454. #endif
  455. {
  456.   struct curText *curtext;
  457.   int len;
  458.  
  459.   curtext = (struct curText *)region->points;
  460.   curtext->string[curtext->char_cnt] = '\0';
  461.   len = strlen(line);
  462.   (void)sprintf(&line[len], ",%1d,\"%s\")",
  463.         curtext->char_cnt, curtext->string);
  464. }
  465.