home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / viewwrld / viewwrld.lha / viewworld / gr / gr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-21  |  23.1 KB  |  860 lines

  1. /* $Id: gr.c,v 2.3 89/09/20 17:01:26 mbp Exp $
  2.  *
  3.  * gr.c: main GR procedures
  4.  */
  5.  
  6. /************************************************************************
  7.  *        Copyright (C) 1989 by Mark B. Phillips                  *
  8.  *                                     *
  9.  * Permission to use, copy, modify, and distribute this software and    *
  10.  * its documentation for any purpose and without fee is hereby granted, *
  11.  * provided that the above copyright notice appear in all copies and    *
  12.  * that both that copyright notice and this permission notice appear in *
  13.  * supporting documentation, and that the name of Mark B. Phillips or   *
  14.  * the University of Maryland not be used in advertising or publicity   *
  15.  * pertaining to distribution of the software without specific, written *
  16.  * prior permission.  This software is provided "as is" without express *
  17.  * or implied warranty.                                                 *
  18.  ************************************************************************/
  19.  
  20. #include <stdio.h>
  21. #include <malloc.h>
  22. #include <math.h>
  23. #include "gr.h"
  24. #include "internal.h"
  25.  
  26. gr_Menu    GR_current_menu;
  27. double    GR_x1, GR_y1, GR_x2, GR_y2, GR_xfactor, GR_yfactor;
  28. int    GR_window_open = 0;
  29. char    *(*GR_coordinate_display_proc)() = NULL;
  30.  
  31. /* NOTE: the following specifies how points are drawn.  This default
  32.  * can be overriden by a specification in the SunView defaults
  33.  * database, which currently is read only by the 3D version of GR
  34.  * (in the file window.c). */
  35. int    GR_point_list_default[] = {0,0, 1,0, -1,0, 0,1, 0,-1};
  36. int    *GR_point_list = GR_point_list_default;
  37. int    GR_point_list_count =
  38.   sizeof(GR_point_list_default)    / (2 * sizeof(int));
  39.  
  40. #define    YES    1
  41. #define    NO    0
  42.  
  43. #define MAX(x,y) ( (x>y) ? (x) : (y) )
  44.  
  45. static int plotting=0;
  46. static FILE *postscript_fp=NULL;
  47. static int batching=0;
  48. static int current_canvas_x = 0;
  49. static int current_canvas_y = 0;
  50.  
  51. /*-----------------------------------------------------------------------
  52.  * Function:     gr_initialize
  53.  * Description:  Initialize the package
  54.  * Arguments:     argc, argv: generic Suntools command line argument list
  55.  *         (list of -W options)
  56.  * Notes:        Must be called before any gr_ procedures other than
  57.  *         ones beginning with gr_preset_.
  58.  */
  59. int
  60. gr_initialize(argc, argv)
  61.      int argc;
  62.      char **argv;
  63. {
  64.   GR_current_menu.title = NULL;
  65.   gr_coordinate_system(0.0, 0.0, 1.0, 1.0);
  66.   return( GR_initialize_windows(argc, argv) );
  67. }
  68.  
  69. /*-----------------------------------------------------------------------
  70.  * Function:     gr_set_frame_icon
  71.  * Description:  Specify a frame icon
  72.  * Arguments IN: *icon: the icon to use
  73.  * Returns:      success status
  74.  */
  75. int
  76. gr_set_frame_icon( icon )
  77. Icon *icon;
  78. {
  79.   if ( (GR_base_frame==NULL) || (icon==NULL) )
  80.     return(1);
  81.   else {
  82.     window_set(GR_base_frame, FRAME_ICON, icon, 0);
  83.     return(0);
  84.   }
  85. }
  86.  
  87. /*-----------------------------------------------------------------------
  88.  * Function:     gr_set_frame_label
  89.  * Description:  Set the frame's label
  90.  * Arguments IN: label: the label to use
  91.  * Returns:      success status
  92.  */
  93. int
  94. gr_set_frame_label( label )
  95. char *label;
  96. {
  97.   if ( (GR_base_frame==NULL) || (label==NULL) )
  98.     return(1);
  99.   else {
  100.     window_set(GR_base_frame, FRAME_LABEL, label, 0);
  101.     return(0);
  102.   }
  103.  
  104. }
  105.  
  106. /*-----------------------------------------------------------------------
  107.  * Function:    gr_set_menu
  108.  * Description:    Set the current (application) menu
  109.  * Args  IN:    *menu: the new menu
  110.  * Notes:    
  111.  */
  112. int
  113. gr_set_menu(new_menu)
  114. gr_Menu *new_menu;
  115. {
  116.   int i, len, maxlen;
  117.   
  118.   if (new_menu==NULL) return(1);
  119.  
  120.   /* If a menu has been specified before, free up its space */
  121.   if (GR_current_menu.title!=NULL) {
  122.     delete_menu(&GR_current_menu);
  123.   }
  124.  
  125.   /* Compute max length of entries in new menu */
  126.   maxlen = strlen(new_menu->title);
  127.   for (i=0; i<new_menu->nopts; ++i) {
  128.     if ( (len=strlen(new_menu->list[i].string)) > maxlen)
  129.       maxlen = len;
  130.   }
  131.  
  132.   /* Install centered title and entries into current menu */
  133.   GR_current_menu.title = malloc((maxlen+1)*sizeof(char));
  134.   strcpy(GR_current_menu.title, GR_center_string(new_menu->title,maxlen));
  135.   GR_current_menu.nopts = new_menu->nopts;
  136.   GR_current_menu.list =
  137.     (gr_Opt_pair*)malloc(new_menu->nopts*sizeof(gr_Opt_pair));
  138.   for (i=0; i<GR_current_menu.nopts; ++i) {
  139.     GR_current_menu.list[i].string = malloc((maxlen+1)*sizeof(char));
  140.     strcpy(GR_current_menu.list[i].string,
  141.        GR_center_string(new_menu->list[i].string, maxlen));
  142.     GR_current_menu.list[i].proc = new_menu->list[i].proc;
  143.   }
  144.   return(0);
  145. }
  146.  
  147. /*-----------------------------------------------------------------------
  148.  * Function:    gr_coordinate_system
  149.  * Description:    Establishes coordinate system of graphics canvas
  150.  * Args IN:    (x1, y1): coords of lower left corner
  151.  *        (x2, y2): coords of upper right corner
  152.  * Notes:   1.    x1 != x2 and y1 != y2 must hold or else and error occurrs.
  153.  *        2.    This procedure can be called more than once; the coordinate
  154.  *        system changes each time.
  155.  *        3.    The default coordinate system is with (0,0) in the lower
  156.  *        left and (1,1) in the upper right.
  157.  */
  158. int
  159. gr_coordinate_system(x1, y1, x2, y2)
  160. double x1, y1, x2, y2;
  161. {
  162.   if ( (x1 == x2) || (y1 == y2) )
  163.     return(1);
  164.   GR_x1 = x1;
  165.   GR_y1 = y1;
  166.   GR_x2 = x2;
  167.   GR_y2 = y2;
  168.   GR_xfactor = GR_canvas_width / (GR_x2 - GR_x1);
  169.   GR_yfactor = GR_canvas_height / (GR_y1 - GR_y2);
  170.   return(0);
  171. }
  172.  
  173. /*-----------------------------------------------------------------------
  174.  * Function:    gr_main_loop
  175.  * Description:    Enter the main Suntools notifier loop
  176.  * Args:    (none)
  177.  * Notes:    This call returns only when one of the following happens:
  178.  *        1. The user clicks the "Quit" button
  179.  *        2. The user picks the "Quit" option from the frame menu.
  180.  *        3. The function gr_done() is called.
  181.  */
  182. int
  183. gr_main_loop()
  184. {
  185.   if (GR_base_frame == NULL) {
  186.     GR_error("You must call gr_init before calling gr_main_loop !");
  187.     return(1);
  188.   }
  189.   else {
  190.  
  191.     /* For development, we use panel_edit: */
  192.     /* paneledit_init(GR_base_frame); */
  193.  
  194.     GR_window_open = 1;
  195.     window_main_loop(GR_base_frame);
  196.     return(0);
  197.   }
  198. }
  199.  
  200. /*-----------------------------------------------------------------------
  201.  * Function:    gr_done
  202.  * Description:    closes the window and causes gr_main_loop to return
  203.  * Args:    (none)
  204.  */
  205. int
  206. gr_done()
  207. {
  208.   window_done(GR_base_frame);
  209. }
  210.  
  211. /*-----------------------------------------------------------------------
  212.  * Function:    gr_canvas_move
  213.  * Description:    move to a new (x,y) in integer canvas coordinates
  214.  * Args  IN:    x,y: new point to move to
  215.  */
  216. int
  217. gr_canvas_move(x,y)
  218.      int x,y;
  219. {
  220.   if (plotting)
  221.     return( GR_postscript_move( x, y ) );
  222.   else {
  223.     current_canvas_x = x;
  224.     current_canvas_y = y;
  225.     return(0);
  226.   }
  227. }    
  228.  
  229. /*-----------------------------------------------------------------------
  230.  * Function:    gr_point
  231.  * Description:    draw a point at current point
  232.  * Args:    (none)
  233.  * Notes:    Points on canvas are drawn according to the coordinates
  234.  *        in the global variable GR_point_list.  This contains
  235.  *        a list of pixels, in integer coordinates relative to
  236.  *        the current position, to be plotted.  The number of
  237.  *        coordinates in GR_point_list is given by the value
  238.  *        of GR_point_list_count.
  239.  */
  240. int
  241. gr_point()
  242. {
  243.   int i;
  244.  
  245.   if (plotting) 
  246.     return( GR_postscript_point() );
  247.   else
  248.     for (i=0; i<GR_point_list_count; ++i)
  249.       pw_put(GR_canvas_pw,
  250.          current_canvas_x+GR_point_list[2*i],
  251.          current_canvas_y+GR_point_list[2*i+1],
  252.          1);
  253.   return(0);
  254. }
  255.  
  256. /*-----------------------------------------------------------------------
  257.  * Function:    gr_canvas_draw
  258.  * Description:    draw to a new (x,y) in canvas integer coords
  259.  * Args  IN:    x,y: coords of new point
  260.  * Notes:    (x,y) becomes the new current point
  261.  */
  262. int
  263. gr_canvas_draw(x,y)
  264.      int x,y;
  265. {
  266.   if (plotting)
  267.     return( GR_postscript_draw(x,y) );
  268.   else {
  269.     pw_vector(GR_canvas_pw,
  270.           current_canvas_x, current_canvas_y, x, y,
  271.           PIX_SRC, 1);
  272.     current_canvas_x = x;
  273.     current_canvas_y = y;
  274.     return(0);
  275.   }
  276. }
  277.  
  278. /* -----------------------------------------------------------------------
  279.  * Function:    gr_canvas_arc
  280.  * Description:    draw a circular arc using integer canvas coordinates
  281.  * Args  IN:    xc,yc: center of arc
  282.  *         x1,y1: initial point of arc
  283.  *         x2,y2: terminal point of arc
  284.  * Notes:    The arc is drawn counterclockwise.  If (x1,y1) and
  285.  *         (x2,y2) are the same point, an entire circle is drawn.
  286.  *         The current point is left unchanged.  (x2,y2) is used
  287.  *         only to determine the final angle of the arc.  The arc
  288.  *         is drawn by drawing line segments at angle_inc
  289.  *         increments.  This increment is computed in terms of
  290.  *         the radius of the arc, so that a circle whose radius
  291.  *         is half the width of the canvas is drawn with an
  292.  *         increment of FULL_ANGLE_INC degrees.
  293.  *
  294.  *        Yes, I know there are much more efficent ways of drawing
  295.  *        arcs.  Dontations of such code will be greatly apprectiated.
  296.  */
  297. int
  298.   gr_canvas_arc( xc,yc,  x1,y1,  x2,y2 )
  299. int xc,yc,x1,y1,x2,y2;
  300. {
  301. #define FULL_ANGLE_INC 2.5
  302.  
  303.   int x,y, xdiff,ydiff, xfinal,yfinal;
  304.   double r1,r2, th1, th2, angle;
  305.   double angle_inc;
  306.   static double angle_factor = FULL_ANGLE_INC * M_PI / (180.0 * 2.0);
  307.   static double max_angle_inc = 15.0 * M_PI / 180.0;
  308.   
  309.   if (plotting) 
  310.     return( GR_postscript_arc(xc,yc,  x1,y1,  x2,y2 ) );
  311.   else {
  312.     /* Always batch around arc drawing */
  313.     if (!batching) pw_batch_on(GR_canvas_pw);
  314.  
  315.     /* Compute radius r1 of arc */
  316.     xdiff = x1-xc;  ydiff = y1-yc;
  317.     r1 = sqrt( (double)(xdiff*xdiff + ydiff*ydiff) );
  318.  
  319.     /* Compute initial and terminal angles */
  320.     th1 = atan2( (double)ydiff, (double)xdiff );
  321.     xdiff = x2-xc;  ydiff = y2-yc;
  322.     r2 = sqrt( (double)(xdiff*xdiff + ydiff*ydiff) );
  323.     th2 = atan2( (double)ydiff, (double)xdiff );
  324.  
  325.     /* Compute exact coordinates of final point */
  326.     xfinal = xc + (int)( r1 * ( (double)xdiff / (double)r2 ) );
  327.     yfinal = yc + (int)( r1 * ( (double)ydiff / (double)r2 ) );
  328.  
  329.     /* Make sure angles are correctly oriented */
  330.     /* if (th2<=th1) th2 += 2*M_PI; */
  331.     if (th2>=th1) th2 -= 2*M_PI;
  332.  
  333.     /* Compute angle increment based on radius r1 */
  334.     angle_inc = angle_factor * ( (double)GR_canvas_width / (double)r1 );
  335.     if (angle_inc>max_angle_inc) angle_inc = max_angle_inc;
  336.  
  337.     /* now DRAW, buster! */
  338.     gr_canvas_move(x1, y1);
  339.     for (angle=th1-angle_inc; angle>th2; angle-=angle_inc) {
  340.       x = xc + (int) ( r1*cos(angle) );
  341.       y = yc + (int) ( r1*sin(angle) );
  342.       gr_canvas_draw(x, y);
  343.     }
  344.     gr_canvas_draw(xfinal, yfinal);
  345.  
  346.     /* Turn batching off if it wasn't already on */
  347.     if (!batching) pw_batch_off(GR_canvas_pw);
  348.  
  349.     return(0);
  350.   }
  351. }
  352.  
  353. /*-----------------------------------------------------------------------
  354.  * Function:    gr_erase
  355.  * Description:    erase the canvas
  356.  * Args:    (none)
  357.  * Notes:    Has no effect in PostScript mode
  358.  */
  359. int
  360. gr_erase()
  361. {
  362.   if (!plotting) {
  363.     pw_writebackground(GR_canvas_pw, 0,0, 
  364.                GR_canvas_width, GR_canvas_height, PIX_SRC);
  365.   }
  366.   return(0);
  367. }
  368.  
  369. /* -----------------------------------------------------------------------
  370.  * Function:       gr_get_canvas_xy
  371.  * Description:       Get a point in canvas integer coords from the user
  372.  * Args     IN:       bmask: tells which buttons to recognize
  373.  *    OUT:       x,y: coords of point selected by user
  374.  *           button: button pressed by user
  375.  * Notes:       bmask should be a logical OR (|) of GR_LEFT,
  376.  *           GR_MIDDLE, GR_RIGHT, GR_SHIFT_LEFT, GR_SHIFT_MIDDLE,
  377.  *           GR_SHIFT_RIGHT, or GR_ESC.  It must include at least
  378.  *           one of these, or else an error occurrs.
  379.  */
  380. int
  381. gr_get_canvas_xy(x, y, button, bmask)
  382.      int *x, *y;
  383.      gr_Button *button, bmask;
  384. {
  385.   return( GR_get_canvas_xy(x, y, button, bmask) );
  386. }
  387.  
  388. /*-----------------------------------------------------------------------
  389.  * Function:    gr_get_xy
  390.  * Description:    Get a point in FP coords from the user
  391.  * Notes:    Exactly like gr_get_canvas_xy except that the point is
  392.  *        converted to FP coords.
  393.  */
  394. int
  395. gr_get_xy(x, y, button, bmask)
  396.      double *x, *y;
  397.      gr_Button *button, bmask;
  398. {
  399.   int ix, iy, r;
  400.  
  401.   r = GR_get_canvas_xy(&ix, &iy, button, bmask);
  402.   *x = GR_SAVNAC_X(ix);
  403.   *y = GR_SAVNAC_Y(iy);
  404.   return(r);
  405. }
  406.  
  407. /* -----------------------------------------------------------------------
  408.  * Function:    gr_set_coordinate_display_proc
  409.  * Description:    specify a procedure to use for displaying coordinates
  410.  *          when user is selecting a point
  411.  * Args     IN:    proc: pointer to coordinate display function
  412.  * Notes:    proc should be declared as follows:
  413.  *            char *proc(x,y)
  414.  *            int x,y;
  415.  *        It should return a pointer to a string to be displayed
  416.  *        in the coordinate display area of the application panel.
  417.  */
  418. int
  419. gr_set_coordinate_display_proc( proc )
  420. char *(*proc)();
  421. {
  422.   if (proc == NULL)
  423.     return(1);
  424.   else {
  425.     GR_coordinate_display_proc = proc;
  426.     return(0);
  427.   }
  428. }
  429.  
  430. /*-----------------------------------------------------------------------
  431.  * Function:    gr_show_canvas_cursor
  432.  * Description:    Move cursor to a given location in canvas integer coords
  433.  * Args  IN:    x,y: coords of point to move cursor to
  434.  * Notes:    
  435.  */
  436. int
  437. gr_show_canvas_cursor(x,y)
  438.      int x,y;
  439. {
  440.   window_set(GR_canvas, WIN_MOUSE_XY, x, y, 0);
  441. }
  442.  
  443. /* -----------------------------------------------------------------------
  444.  * Function:    gr_button_message
  445.  * Description:    display button messages in application panel
  446.  * Args  IN:    Lmsg:   message for left mouse button
  447.  *         Mmsg:   message for middle mouse button
  448.  *         Rmsg:   message for right mouse button
  449.  *         SLmsg:  message for shifted left mouse button
  450.  *         SMmsg:  message for shifted middle mouse button
  451.  *         SRmsg:  message for shifted right mouse button
  452.  *         ESCmsg: message for ESCAPE key
  453.  * Notes:    The image corresponding to a button is displayed only
  454.  *         if that button's message has nonzero length, i.e. is
  455.  *         other than "".
  456.  */
  457. int
  458. gr_button_message(Lmsg, Mmsg, Rmsg, SLmsg, SMmsg, SRmsg, ESCmsg)
  459.      char  *Lmsg, *Mmsg, *Rmsg, *SLmsg, *SMmsg, *SRmsg, *ESCmsg;
  460. {
  461.   return( GR_show_mouse_message(0, Lmsg)  |
  462.       GR_show_mouse_message(1, Mmsg)  |
  463.       GR_show_mouse_message(2, Rmsg)  |
  464.       GR_show_mouse_message(3, SLmsg) |
  465.       GR_show_mouse_message(4, SMmsg) |
  466.       GR_show_mouse_message(5, SRmsg) |
  467.       GR_show_mouse_message(6, ESCmsg)  );
  468. }
  469.  
  470. /*-----------------------------------------------------------------------
  471.  * Function:    gr_button_message_clear
  472.  * Description:    clear all button messages
  473.  * Args:    (none)
  474.  */
  475. int
  476. gr_button_message_clear()
  477. {
  478.   return( gr_button_message( "", "", "", "", "", "", "" ) );
  479. }
  480.  
  481. /*-----------------------------------------------------------------------
  482.  * Function:    gr_message
  483.  * Description:    display a message in one of the application message lines
  484.  * Args  IN:    s: the message string
  485.  *        n: the number of the message line to use (1,2)
  486.  * Notes:    The message numbers here are 1,2. The message numbers
  487.  *        used in window.c, however, are 0,1.
  488.  */
  489. int
  490. gr_message(s, n )
  491.      char *s;
  492.      int n;
  493. {
  494.   return( GR_show_app_message(n-1, s) );
  495. }
  496.  
  497. /*-----------------------------------------------------------------------
  498.  * Function:    gr_message_clear
  499.  * Description:    clear all application panel messages
  500.  * Args:    (none)
  501.  */
  502. int
  503. gr_message_clear()
  504. {
  505.   int i, r;
  506.  
  507.   r = 0;
  508.   for (i=0; i<4; ++i) r |= gr_message("", i);
  509.   return(r);
  510. }
  511.  
  512. /*-----------------------------------------------------------------------
  513.  * Function:    gr_get_string
  514.  * Description:    get a string from the user
  515.  * Args  IN:    s: pointer to location where string is to be stored
  516.  * Notes:    The maximum length of a string returned by this
  517.  *        procedure will be GR_INPUT_STRING_LENGTH, not including
  518.  *        the terminal null character.
  519.  */
  520. int
  521. gr_get_string(s)
  522. {
  523.   return( GR_app_panel_get_string(s) );
  524. }
  525.  
  526. /*-----------------------------------------------------------------------
  527.  * Function:    gr_batch_on
  528.  * Description:    turn graphics batching on
  529.  * Args:    (none)
  530.  */
  531. int
  532. gr_batch_on()
  533. {
  534.   batching = YES;
  535.   pw_batch_on(GR_canvas_pw);
  536. }
  537.  
  538. /*-----------------------------------------------------------------------
  539.  * Function:    gr_batch_off
  540.  * Description:    turn graphics batching off
  541.  * Args:    (none)
  542.  */
  543. int
  544. gr_batch_off()
  545. {
  546.   batching = NO;
  547.   pw_batch_off(GR_canvas_pw);
  548. }
  549.  
  550. /*-----------------------------------------------------------------------
  551.  * Function:    gr_set_help_file
  552.  * Description:    specify the name of the file to display in the help window
  553.  * Args  IN:    filename: the file's name
  554.  * Notes:    This does not change the visibility status of the
  555.  *        help window
  556.  */
  557. gr_set_help_file(filename)
  558. char *filename;
  559. {
  560.   return( GR_set_help_file(filename) );
  561. }
  562.  
  563. /*-----------------------------------------------------------------------
  564.  * Function:    gr_aspect_ratio
  565.  * Description:    get the aspect ratio of the canvas
  566.  * Args:    (none)
  567.  * Returns:    the ratio ( canvas_width / canvas_height )
  568.  */
  569. double
  570. gr_aspect_ratio()
  571. {
  572.   return( (double)GR_canvas_width / (double)GR_canvas_height );
  573. }
  574.  
  575. /*-----------------------------------------------------------------------
  576.  * Function:    gr_canvas_width
  577.  * Description:    get the width of the canvas
  578.  * Args:    (none)
  579.  * Returns:    the canvas width in pixels
  580.  */
  581. int
  582. gr_canvas_width()
  583. {
  584.   return(GR_canvas_width);
  585. }
  586.  
  587. /*-----------------------------------------------------------------------
  588.  * Function:    gr_canvas_height
  589.  * Description:    get the height of the canvas
  590.  * Args:    (none)
  591.  * Returns:    the canvas height in pixels
  592.  */
  593. int
  594. gr_canvas_height()
  595. {
  596.   return(GR_canvas_height);
  597. }
  598.  
  599. /*-----------------------------------------------------------------------
  600.  * Function:    gr_user_confirm
  601.  * Description:    force user to answer yes or no to a question
  602.  * Args  IN:    s: the question to ask
  603.  * Returns:    1 for yes, 0 for no
  604.  * Notes:    This procedure blocks everything until the user answers
  605.  */
  606. int
  607. gr_user_confirm(s)
  608. {
  609.   return(GR_user_confirm(s));
  610. }
  611.  
  612. /*-----------------------------------------------------------------------
  613.  * Function:    gr_postscript_begin
  614.  * Description:    begin a PostScript file
  615.  * Args  IN:    fname: the name of the file to write PostScript to
  616.  *        logo: string to use as program logo on picture
  617.  *        label: string to use as picture's label
  618.  *        time: string to use as time stamp on picture
  619.  * Notes:    Any of logo, label, and time may be NULL, in which case
  620.  *        it does not appear on the picture.
  621.  */
  622. int
  623. gr_postscript_begin(fname, logo, label, time)
  624.      char *fname, *logo, *label;
  625. {
  626.   if (plotting) return(1);
  627.   postscript_fp = fopen(fname, "w");
  628.   if (postscript_fp == NULL) return(1);
  629.   if (GR_begin_postscript_file(postscript_fp, logo, label, time) != 0)
  630.     return(1);
  631.   plotting = YES;
  632.   return(0);
  633. }
  634.  
  635. /*-----------------------------------------------------------------------
  636.  * Function:    gr_postscript_end
  637.  * Description:    quit writing a PostScript file
  638.  * Args:    (none)
  639.  */
  640. int
  641. gr_postscript_end()
  642. {
  643.   int r;
  644.  
  645.   if (!plotting) return(1);
  646.   r = GR_end_postscript_file(postscript_fp);
  647.   r |= fclose(postscript_fp);
  648.   plotting = NO;
  649.   return(r);
  650. }
  651.  
  652. /*-----------------------------------------------------------------------
  653.  * Function:    gr_print_button
  654.  * Notes:    See GR_print_button (in window.c) for details
  655.  */
  656. int
  657. gr_print_button(status, redraw_proc, logo)
  658.      int status;
  659.      int (*redraw_proc)();
  660.      char *logo;
  661. {
  662.   return( GR_print_button(status,redraw_proc,logo) );
  663. }
  664.  
  665. /*-----------------------------------------------------------------------
  666.  * Function:    gr_signal
  667.  * Description:    set a trap for a Unix signal
  668.  * Args  IN:    sig: the signal to catch
  669.  *        func: the function to call when the signal is caught
  670.  * Notes:    GR applications should call this instead of signal(3)
  671.  *        in order to peacefully exist with the notifier.
  672.  */
  673. gr_signal(sig, func)
  674. int sig, (*func)();
  675. {
  676.   notify_set_signal_func(GR_base_frame, func, sig, NOTIFY_ASYNC);
  677. }
  678.  
  679. /*-----------------------------------------------------------------------
  680.  * Function:    gr_set_input_func
  681.  * Description:    specify a function to call when input is available from
  682.  *        a pipe
  683.  * Args  IN:    func: the function to call
  684.  *        fd: file descriptor of pipe
  685.  */
  686. gr_set_input_func(func, fd)
  687. int (*func)(), fd;
  688. {
  689.   notify_set_input_func(GR_base_frame, func, fd);
  690. }
  691.  
  692. /*-----------------------------------------------------------------------
  693.  * Function:    gr_iconic
  694.  * Description:    change whether the window is iconic
  695.  * Args  IN:    state: 0 for non-iconic, 1 for iconic
  696.  */
  697. gr_iconic(state)
  698. int state;
  699. {
  700.   if (state==1)
  701.       window_set( GR_base_frame, FRAME_CLOSED, TRUE, 0 );
  702.   else
  703.       window_set( GR_base_frame, FRAME_CLOSED, FALSE, 0 );
  704. }
  705.  
  706. /*-----------------------------------------------------------------------
  707.  * Function:     GR_file_openable
  708.  * Description:  Find out if a file can be opened with a given mode
  709.  * Arguments IN: filename: the name of the file
  710.  *         mode: the mode to check for
  711.  * Returns:      1 means yes, 0 means no
  712.  */
  713. int
  714. GR_file_openable(filename, mode)
  715.      char *filename, *mode;
  716. {
  717.   FILE *fp;
  718.  
  719.   if ( (fp=fopen(filename,mode)) == NULL )
  720.     return(0);
  721.   else {
  722.     fclose(fp);
  723.     return(1);
  724.   }
  725. }
  726.  
  727. /*-----------------------------------------------------------------------
  728.  * Function:     GR_center_string
  729.  * Description:  center a string in a string of a given length
  730.  * Arguments IN: s: string to be centered
  731.  *          OUT: n: length of string to center s in; this does NOT include
  732.  *           the final null character
  733.  * Returns:      the centered string
  734.  * Notes:        The returned string is stored in dynamic storage which
  735.  *               is freed on the next call. If n <= strlen(s), the first
  736.  *               n chars of s are returned.
  737.  */
  738. char *
  739. GR_center_string(s,n)
  740.      char *s;
  741.      int n;
  742. {
  743.   static char *answer = NULL;
  744.   int i,len,padlen;
  745.  
  746.   if (answer!=NULL) free(answer);
  747.   answer = malloc((n+1)*sizeof(char));
  748.   for (i=0; i<n; ++i) answer[i] = ' ';
  749.   len = strlen(s);
  750.   padlen = MAX( (n-len)/2, 0 );
  751.   for (i=0; (i<len) && (i+padlen<n); ++i) answer[padlen+i] = s[i];
  752.   answer[n] = '\0';
  753.   return(answer);
  754. }
  755.  
  756. #ifdef THREE_D            /* procedures for 3D version only */
  757.  
  758. int
  759. gr_set_eye_display(eye)
  760.      double *eye;
  761. {
  762.   return(GR_set_view_display(GR_EYE, eye));
  763. }
  764.  
  765. int
  766. gr_set_focus_display(focus)
  767.      double *focus;
  768. {
  769.   return(GR_set_view_display(GR_FOCUS, focus));
  770. }
  771.  
  772. int
  773. gr_set_up_display(up)
  774.      double *up;
  775. {
  776.   return(GR_set_view_display(GR_UP,up));
  777. }
  778.  
  779. int
  780. gr_set_view_plane_window_display(u1,u2, v1,v2)
  781.      double u1,u2,v1,v2;
  782. {
  783.   double values[4];
  784.  
  785.   values[0] = u1;  values[1] = u2;
  786.   values[2] = v1;  values[3] = v2;
  787.   return(GR_set_view_display(GR_VPW, values));
  788. }
  789.  
  790. int
  791. gr_get_eye_display(eye)
  792.      double *eye;
  793. {
  794.   return(GR_get_view_display(GR_EYE, eye));
  795. }
  796.  
  797. int
  798. gr_get_focus_display(focus)
  799.      double *focus;
  800. {
  801.   return(GR_get_view_display(GR_FOCUS, focus));
  802. }
  803.  
  804. int
  805. gr_get_up_display(up)
  806.      double *up;
  807. {
  808.   return(GR_get_view_display(GR_UP,up));
  809. }
  810.  
  811. int
  812. gr_get_view_plane_window_display(u1,u2, v1,v2)
  813.      double *u1,*u2,*v1,*v2;
  814. {
  815.   double values[4];
  816.   int r;
  817.  
  818.   r = GR_get_view_display(GR_VPW, values);
  819.   *u1 = values[0]; *u2 = values[1];
  820.   *v1 = values[2]; *v2 = values[3];
  821.   return(r);
  822. }
  823.  
  824. #endif            /* End of procedures for 3D version only */
  825.  
  826. /************************************************************************
  827.  *
  828.  *         P R I V A T E    P R O C E D U R E S
  829.  *
  830.  *     Anything below here is for use only within this file
  831.  ************************************************************************/
  832.  
  833. /*-----------------------------------------------------------------------
  834.  * Function:    delete_menu
  835.  * Description:    Free up the space associated with a gr_Menu struct, and
  836.  *        re-initialize its entries
  837.  * Args  IN:    *m: the menu
  838.  */
  839. static int
  840. delete_menu(m)
  841.      gr_Menu *m;
  842. {
  843.   int i;
  844.  
  845.   if (m==NULL)
  846.     return(1);
  847.   else {
  848.     if (m->title!=NULL) free(m->title);
  849.     if (m->list!=NULL) {
  850.       for (i=0; i<m->nopts; ++i)
  851.     if (m->list[i].string!=NULL) free(m->list[i].string);
  852.       free(m->list);
  853.     }
  854.     m->nopts = 0;
  855.     return(0);
  856.   }
  857.  
  858. }
  859.  
  860.