home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / d / dots151.zip / GRAPHSRC.ZIP / GMOUSE.C < prev    next >
C/C++ Source or Header  |  1990-06-16  |  28KB  |  976 lines

  1. #define RR(x)    /* sprintf x; note(buf); scr_ci()       /**/
  2. #define NOMOUSE
  3. /*
  4.     gmouse - mouse handler for graph
  5.  
  6.     The top level routine here is adjust_parameters.  It expects
  7.     the calling program to have put the screen into graphics mode.
  8.  
  9. #include <string.h>
  10. */
  11. #include <stdio.h>
  12. #include <math.h>
  13.  
  14. #ifdef __DESMET__
  15. #define far
  16. #else
  17. #include <string.h>
  18. #endif
  19. #define exp10(x) exp((x)*2.302585093)    /* 10**x */
  20.  
  21. #include "scr_ci.h"
  22. #include "g.h"
  23. #include "graph.h"
  24. #include "window.h"
  25.  
  26. #define ENTRIES 5000
  27. #define MAXSTYLES 100
  28. #define MIN_GRID_STYLE (-4)
  29. #define BUFSIZE 200
  30.  
  31.             /* local functions */
  32. static        MODEL adjust_abscissas( );
  33. static        MODEL adjust_grid( );
  34. static        MODEL adjust_label( );
  35. static        MODEL adjust_limits( float *x, double *min, double *max, 
  36.                                                 int *log_scale, float *y ); 
  37. static        MODEL adjust_styles( );
  38. static        MODEL adjust_window( MESSAGE msg, int *data, WINDOW *pw );
  39. static double MODEL fetch_value( double deflt, double least, double most );
  40. static        MODEL GetStyleCode( char *buf );
  41. static        MODEL script_file( int *argcp, char ***argvp );
  42. static        MODEL ShowStyles( MESSAGE msg, int *data, WINDOW *pw );
  43. static        MODEL show_style( char *buf, int n, int style );
  44.  
  45. extern char buf[BUFSIZE];
  46. char buf2[BUFSIZE];
  47. extern char *text_label, *default_label;
  48. extern double xmin, xmax, xdel, ymin, ymax, ydel;
  49. extern double
  50.     requested_height_used,    /* fraction of vertical space used */
  51.     requested_width_used,    /* fraction of horizontal space used    */
  52.     requested_right_move,    /* fraction of space to move right before plotting */
  53.     requested_up_move,        /* fraction of space to move up before plotting */
  54.     abscissa,            /* current value for automatic abscissas */
  55.     abscissa_start,        /* default starting value for automatic abscissas */
  56.     abscissa_step;        /* default step for automatic abscissas */
  57.  
  58. extern int breaking;    /* nonzero if breaking (disconnecting) 
  59.                                         graph after each label in input */
  60. extern int equal;        /* nonzero if vertical and horizontal 
  61.                                         scales must be equal */
  62. extern int debugging;
  63. extern int default_labeling;    /* nonzero if default point label was given */
  64. extern int grid_width;            /* width of grid lines */
  65. extern int grid_style;            /* 0 for no grid, 1 for frame with tics,
  66.                                         2 for full grid */
  67. extern int numeric_labeling;
  68. extern int out_of_memory;        /* set nonzero when malloc fails */
  69. extern int transposing;            /* nonzero if transposing x & y */
  70. extern int labels;                /* number of user-supplied labels */
  71. extern int logx;                /* nonzero if x axis is to be logrithmic */
  72. extern int logy;                /* nonzero if y axis is to be logrithmic */
  73. extern int requested_rlx;        /* approximate number of x axis labels */
  74. extern int requested_rtx;        /* requested # tics on axis */
  75. extern int requested_rly;        /* approximate number of y axis labels */
  76. extern int requested_rty;        /* requested # tics on axis */
  77. extern int standard_input;        /* nonzero if data is from standard input */
  78. extern int text_labeling;
  79. extern int x_arguments;            /* number specified: xmin, xmax, xdel    */
  80. extern int y_arguments;            /* number specified: ymin, ymax, ydel    */
  81. extern int style[MAXSTYLES];    /* array of requested line styles    */
  82. extern int repeat[MAXSTYLES];    /* array of repeat counts for line styles    */
  83. extern int numstyles;            /* # linestyles specified by user */
  84. extern int automatic_abscissas;    /* nonzero if abscissas are to be generated */
  85. extern int magnitude;            /* nonzero if showing magnitude of complex # */
  86. extern int max_points;            /* # x or y points */
  87. extern int phase;                /* nonzero if displaying phase of complex # */
  88. extern int dividing_by_pi;        /* nonzero if dividing phase by pi */
  89. extern int last;                /* number of entries in x and y */
  90. extern FILE *file;
  91. extern float *x, *y;
  92.  
  93. extern int set_linestyle(), set_linewidth(), set_color_or_intensity();
  94. extern int (*after_line)(); 
  95. int (*set_line_attribute)() = set_linewidth;
  96.  
  97. extern double            /* imported from g31.c */
  98. rot11, rot12, rot13, rot14,     /* rotation & projection matrix */
  99. rot21, rot22, rot23, rot24;
  100.  
  101.     typedef struct _blk
  102.         {struct _blk *nxt;
  103.         int num;
  104.         char txt[1];
  105.         } BLOCK;
  106. extern BLOCK *top_label;
  107.  
  108. extern char *default_script_file;
  109.  
  110. static int mouseInstalled = 0;
  111.  
  112. #define BIG 1.e100
  113. #define up_char 30
  114. #define down_char 31
  115.  
  116. static MENU *main_men, *x_men, *f_men, *s_men, *g_men, *a_men;
  117.  
  118. WINDOW *bwin, *qwin, *dwin;
  119.  
  120. double fetch_value(deflt, least, most) double deflt, least, most;
  121. {    double value, eps;
  122.  
  123.     eps = .000001*(most - least);
  124.     while(1)
  125.         {
  126.         sprintf(buf, "%2.4g", deflt);
  127.  
  128.         WinGetString("new value?", buf, 0, char_width, 2*char_height, qwin);
  129.  
  130.         if(!buf[0]) {value = deflt; break;}
  131.         value = atof(buf);
  132.         if(least - eps < value && value < most + eps) break;
  133.         sprintf(buf, "must be in range %2.4g ... %2.4g", least, most);
  134.         note(buf);
  135.         }
  136.     if(dwin->vis) (*dwin->accept)(CLEAR, NULL, dwin);
  137.     (*qwin->accept)(CLEAR, NULL, qwin);
  138. /*
  139.     scr_rowcol(23, 0);
  140.     if(.1 < fabs(value) && fabs(value) < 1.) 
  141.         printf("value revised to %5.4f", value);
  142.     else 
  143.         printf("value revised to %2.4g", value);
  144.     scr_clrl();
  145. */
  146.     return value;
  147. }
  148.  
  149. static note(format, s) char *format, *s;
  150. {    sprintf(buf, format, s);
  151.     if(dwin->vis) (*dwin->accept)(CLEAR, NULL, dwin);
  152.     WinShowString(buf, char_width, char_height, dwin);
  153. }
  154.  
  155. BUTTON x_strings[] = 
  156.     {
  157.         {" min & max", "m", "m"},    /* "adjust limits of data to be shown", */
  158.         {" log/linear", "l", "l"},    /* "log/linear scale (toggle)", */
  159.         {0}
  160.     };
  161.  
  162. adjust_limits(x, min, max, log_scale, y) 
  163. float *x, *y; 
  164. double *min, *max; 
  165. int *log_scale;
  166. {    int c, ch, i, j, cur_style, cur_repeat, warned;
  167.     double new_min, new_max, data_min, data_max, temp;
  168.     char *finish_msg;
  169.     static char log_msg[] = "log scale", lin_msg[] = "linear scale",
  170.         discard_msg[] = "nonpositive points discarded";
  171.     BLOCK *current_label, **ppb;
  172.  
  173.     c = MenuResponse(x_men);
  174.     warned = 0;
  175.     switch(c)
  176.         {case 'm': 
  177.             while(1)
  178.                 {
  179.                 if(*log_scale) {new_min = exp10(*min); new_max = exp10(*max);}
  180.                 else {new_min = *min; new_max = *max;}
  181.                 sprintf(buf, "%2.4g %2.4g", new_min, new_max);
  182.                 ch = WinGetString("new limits?", buf, 0, char_width, 
  183.                                                         2*char_height, qwin);
  184.  
  185.                 if(ch ==  0 || ch ==  up_char || !buf[0]) goto X_QUIT;
  186.                 sscanf(buf, "%lf %lf", &new_min, &new_max);
  187.                 if(new_min >= new_max)
  188.                     note("  must have min < max");
  189.                 else if(*log_scale && new_min<=0.) 
  190.                     note(" need positive values for log scale");
  191.                 else break;
  192.                 }
  193.             if(dwin->vis) (*dwin->accept)(CLEAR, NULL, dwin);
  194.             (*qwin->accept)(CLEAR, NULL, qwin);
  195. /*
  196.             printf("limits revised to %2.4g %2.4g", new_min, new_max);
  197. */
  198.             if(*log_scale) 
  199.                 {new_min = log10(new_min); 
  200.                 new_max = log10(new_max);
  201.                 }
  202.             *min = new_min;
  203.             *max = new_max;
  204.             break;
  205.         case 'l': 
  206.             {
  207.             if(*log_scale)
  208.                 {
  209.                 finish_msg = lin_msg;
  210.                 *min = exp10(*min);
  211.                 *max = exp10(*max);
  212.                 for (i = 0; i  <=  last; i++) x[i] = (float)exp10(x[i]);
  213.                 *log_scale = 0;
  214.                 }
  215.             else
  216.                 {finish_msg = log_msg;
  217.                             /*    discard nonpositive data points */
  218.                 current_label = top_label;
  219.                 for (i = j = 0; i  <=  last; i++)
  220.                     {
  221.                     temp = (double)x[i];
  222.                     if(temp > 0.) 
  223.                         {y[j] = y[i];
  224.                         x[j++] = (float)log10(temp);
  225.                         }
  226.                     if(current_label->num == i) 
  227.                         {current_label->num = j?j-1:0;
  228.                         current_label = current_label->nxt;
  229.                         }
  230.                     }
  231.                 if(j == 0)
  232.                     {
  233.                     note("there are no positive data values");
  234.                     scr_ci();        /* wait for one keystroke */
  235.                     terminate(1);
  236.                     }
  237.                 else if(last != j-1) finish_msg = discard_msg;
  238.                 last = j - 1;
  239.  
  240.                             /*    keep last label for each point */
  241.                 ppb = &top_label;
  242.                 if(*ppb)
  243.                     {
  244.                     i = j = 0;
  245.                     cur_style = style[i];
  246.                     cur_repeat = repeat[i];
  247.                     repeat[j] = 0;
  248.                     while((*ppb)->nxt)
  249.                         {
  250.                         if((*ppb)->num == (*ppb)->nxt->num)
  251.                             {                            /* discard a label */
  252.                             *ppb = (*ppb)->nxt;
  253.  
  254.                             labels--;
  255.                             }
  256.                         else
  257.                             {                            /* keep a label */
  258.                             ppb = &((*ppb)->nxt);
  259.                             if(cur_style != style[j]) 
  260.                                 {
  261.                                 style[++j] = cur_style;
  262.                                 repeat[j] = 0;
  263.                                 }
  264.                             repeat[j]++;
  265.                             }
  266.                         if(--cur_repeat <= 0) 
  267.                             {cur_repeat = repeat[++i];
  268.                             cur_style = style[i];
  269.                             }
  270.                         }
  271.                     }
  272.                             /*
  273.                                 if current lower or upper limit is now
  274.                                 invalid (nonpositive), replace with
  275.                                 minimum (or maximum) remaining data value
  276.                             */
  277.                 data_min = data_max = x[0];
  278.                 for (i = 1; i <= last; i++)
  279.                     {temp = (double)x[i];
  280.                     if(temp<data_min) data_min = temp;
  281.                     if(temp>data_max) data_max = temp;
  282.                     }
  283.                 if(*min <= 0.) *min = exp10(data_min);
  284.                 if(*max <= *min) *max = exp10(data_max);
  285.                 take_log(min);
  286.                 take_log(max);
  287.  
  288.                 *log_scale = 1;
  289.                 }
  290.             note(finish_msg);
  291.             break;
  292.             }
  293.         }
  294. X_QUIT:
  295.     (*x_men->accept)(CLEAR, NULL, x_men);
  296.     if(qwin->vis) (*qwin->accept)(CLEAR, NULL, qwin);
  297. }
  298.  
  299. BUTTON a_strings[] = 
  300. {
  301.     {" start", "s", "s"},         /* "abscissa starting value", */
  302.     {" increment", "i", "i"},     /* "abscissa increment", */
  303.     {0}
  304. };
  305.  
  306. adjust_abscissas()
  307. {    int c, i;
  308.     double val;
  309.     BLOCK *current_label;
  310.  
  311.     if(automatic_abscissas)
  312.         {while(c = MenuResponse(a_men))
  313.             {switch(c)
  314.                 {case 'i': 
  315.                     abscissa_step = fetch_value(abscissa_step, -BIG, BIG);
  316.                     break;
  317.                 case 's': 
  318.                     abscissa_start = fetch_value(abscissa_start, -BIG, BIG);
  319.                     break;
  320.                 }
  321.             }
  322.         (*a_men->accept)(CLEAR, NULL, a_men);
  323.         }
  324.     else
  325.         {
  326.         for (i=0; i <= last; i++) y[i] = x[i];
  327.         automatic_abscissas = 1;
  328.         ymin = xmin;
  329.         ymax = xmax;
  330.         note("old y values discarded");
  331.         }
  332.     xmin = xmax = val = abscissa_start;
  333.     current_label = top_label;
  334.     for (i=0; i <= last; i++) 
  335.         {x[i] = (float)val;
  336.         if(val < xmin) xmin = val;
  337.         if(val > xmax) xmax = val;
  338.         val += abscissa_step;
  339.         if(current_label->num == i) 
  340.             {val = abscissa_start;
  341.             current_label = current_label->nxt;
  342.             }
  343.         }
  344.     automatic_abscissas = 1;
  345. }
  346.  
  347. BUTTON s_strings[] = 
  348. {
  349.     {" 0", "0", "0"},
  350.     {" 1", "1", "1"},
  351.     {" 2", "2", "2"},
  352.     {" 3", "3", "3"},
  353.     {" 4", "4", "4"},
  354.     {" 5", "5", "5"},
  355.     {" 6", "6", "6"},
  356.     {" 7", "7", "7"},
  357.     {" 8", "8", "8"},
  358.     {" 9", "9", "9"},
  359.     {" a", "a", "a"},
  360.     {" b", "b", "b"},
  361.     {" c", "c", "c"},
  362.     {" d", "d", "d"},
  363.     {" e", "e", "e"},
  364.     {" f", "f", "f"},
  365.     {" previous    ", "p", "p"},
  366.     {0}
  367. };
  368.  
  369. #ifndef NOMOUSE
  370.  
  371. void ShowStyles(msg, data, pw) MESSAGE msg; int *data; WINDOW *pw;
  372. {    int i, x0, x1, y0;
  373.  
  374.     if(msg == REDRAW) 
  375.         {MsgMenu(msg, data, pw);
  376.         HideMouseCursor();
  377.         x0 = pw->x + 2*char_width;
  378.         x1 = x0 + 10*char_width;
  379.         y0 = pw->y + char_height/2;
  380.         for (i = 0; i < 16; i++)
  381.             {
  382.             (*set_line_attribute)(i);
  383.             (*after_line)(x0, y0, x1, y0);
  384.             y0 += char_height;
  385.             }
  386.         (*draw_line)(data[0], data[1], data[2], data[3]);
  387.         ShowMouseCursor();
  388.         }
  389.     else 
  390.         MsgMenu(msg, data, pw);
  391. }
  392. #endif /* NOMOUSE */
  393.  
  394. GetStyleCode(buf) char *buf;
  395. {    int ch, code;
  396.  
  397.     set_linestyle(0);
  398.     set_linewidth(1);
  399.     set_color_or_intensity(0);
  400.     
  401.     set_line_attribute = set_linewidth;
  402.     ch = MenuResponse(s_men);
  403.     if(ch == 'p' || ch == 0) return ch;
  404.     else if(ch == ' ') return RETURN;
  405.     code = ch - '0';
  406.  
  407.     set_line_attribute = set_color_or_intensity;
  408.     ch = MenuResponse(s_men);
  409.     if(ch == 'p' || ch == 0) return ch;
  410.     else if(ch == ' ') return RETURN;
  411.     code = code*16 + ch - '0';
  412.  
  413.     set_line_attribute = set_linestyle;
  414.     ch = MenuResponse(s_men);
  415.     if(ch == 'p' || ch == 0) return ch;
  416.     else if(ch == ' ') return RETURN;
  417.     code = code*16 + ch - '0';
  418.  
  419.     show_style(buf, 1, code);
  420.     return RETURN;
  421. }
  422.  
  423. adjust_styles()
  424. {
  425.     int i, j, ch, num;
  426.     char *s, *token;
  427.  
  428.     i = 0;
  429.     while(1)
  430.         {if(i == numstyles && i < MAXSTYLES) 
  431.             {style[i] = repeat[i] = 1;
  432.             numstyles++;
  433.             }
  434.         sprintf(buf2, "line style for group %2d: ", i);
  435.         show_style(buf, repeat[i], style[i]);
  436.         ch = WinGetString(buf2, buf, 0, char_width, 2*char_height, qwin); 
  437.         (*qwin->accept)(CLEAR, NULL, qwin);
  438. /*
  439.         ch = GetStyleCode(buf);
  440.         (*s_men->accept)(CLEAR, NULL, s_men);
  441.         if(ch == 'p' && i) repeat[i - 1]++;
  442.         else
  443. */
  444.  
  445.         if(ch == 0) break;
  446.         else if(ch == up_char) 
  447.             {if(i > 0) i--;
  448.             }
  449.         else if(ch == down_char)
  450.             {if(i < numstyles) i++;
  451.             }
  452.         else
  453.             {                                /* delete this style */
  454.             for (j=i; j<numstyles-1; j++) 
  455.                 {style[j] = style[j+1];
  456.                 repeat[j] = repeat[j+1];
  457.                 }
  458.             numstyles--;
  459.             if(token = strtok(buf, " "))
  460.                 {do
  461.                     {                        /* insert a style */
  462.                     if(numstyles == MAXSTYLES) break;
  463.                     for (j = numstyles++; j > i; j--)
  464.                         {style[j] = style[j-1];
  465.                         repeat[j] = repeat[j-1];
  466.                         }
  467.                     num = 1;
  468.                     if(s = strchr(token,'*'))
  469.                         {num = atoi(token);
  470.                         s++;
  471.                         }
  472.                     else s = token;
  473.                     repeat[i] = num<1 ? 1 : num;
  474.                     style[i++] = atox(s);
  475.                     } while (token = strtok(0, " "));
  476.                 }
  477.             }
  478.         }
  479.     if(numstyles > 1) breaking = 1;
  480. /*    (*qwin->accept)(CLEAR, NULL, qwin); */
  481. }
  482.  
  483. show_style(buf, n, style) char *buf; int n, style;
  484. {    char stylebuf[10];
  485.     if(n > 1) sprintf(buf, "%d*", n); else buf[0] = 0;
  486.     if(style<0) sprintf(stylebuf, "-%x", -style);
  487.     else sprintf(stylebuf, "%x", style);
  488.     strcat(buf, stylebuf);
  489. }
  490.  
  491. BUTTON main_strings[] = 
  492. {
  493.     {" / (redraw)", "/", "/"},    /*     "redisplay graph",    */
  494.     {" abscissas", "a", "a"},    /*  "automatically generate abscissas",    */
  495.     {" break     +-", "b", "b"},    /*     "break line after each label (toggle)",    */
  496.     {" equal     +-", "e", "e"},    /*     "equal vertical and horizontal scales (toggle)",    */
  497.     {" file", "f", "f"},            /*     "script file input/output",    */
  498.     {" grid", "g", "g"},            /*     "grid style",    */
  499.     {" label", "l", "l"},        /*  "label for top of graph",    */
  500.     {" marker", "m", "m"},        /*     "marker and line styles",    */
  501.     {" numbers   +-", "n", "n"},    /*     "numeric labels on axes (toggle)",    */
  502.     {" quit", "q", "q"},            /*     "terminate program",    */
  503.     {" transpose +-", "t", "t"},    /*  "transpose x and y axes (toggle)",    */
  504.     {" x", "x", "x"},            /*     "x axis plotting range",    */
  505.     {" y", "y", "y"},            /*     "y axis plotting range",    */
  506.     {" right", "r", "r"},        /*     "offset of plot to right",    */
  507.     {" up", "u", "u"},            /*     "offset of plot upwards",    */
  508.     {" height", "h", "h"},        /*     "height of plot",    */
  509.     {" width", "w", "w"},        /*     "width of plot",    */
  510.     {" zoom", "z", "z"},            /*    "zoom out",    */
  511. /*    {" debug", "d", "d"},            /*    "debug mouse code",    */
  512.     {0}
  513. };
  514.  
  515.  
  516. adjust_parameters(argcp, argvp) int *argcp; char ***argvp;
  517. {    int c, i;
  518.     double d;
  519.     float *pf;
  520.     static int WasReset = 0, numButtons, status, horiz, vert;
  521.  
  522. #ifndef NOMOUSE
  523.     if(mouseInstalled)
  524.         {
  525.         if(!WasReset) {FlagReset(&status, &numButtons); WasReset = 1;}
  526.         do
  527.             {GetPosBut(&status, &horiz, &vert);
  528.             } while (status);
  529.         SetEventHandler(1 + 2 + 4 + 8, MouseHandler);
  530.         ShowMouseCursor();
  531.         }
  532. #endif 
  533.  
  534.     while(c = MenuResponse(main_men))
  535.         {if(c == '/') break;
  536.         switch(c)
  537.             {case 'e': 
  538.                 equal ^= 1; 
  539.                 note("%sequal scales", equal ? "" : "un");
  540.                 break;
  541.             case 'a': adjust_abscissas(); break;
  542.             case 'l': adjust_label(); break;
  543.             case 'm': adjust_styles(); break;
  544.             case 't': 
  545.                 transposing ^= 1; 
  546.                 i = logx; logx = logy; logy = i;
  547.                 pf = x; x = y; y = pf;
  548.                 d = xmin; xmin = ymin; ymin = d;
  549.                 d = xmax; xmax = ymax; ymax = d;
  550.                 d = xdel; xdel = ydel; ydel = d;
  551.                 note("%stransposing scales", transposing ? "" : "not ");
  552.                 break;
  553.             case 'f':
  554.                 script_file(argcp, argvp);
  555.                 break;
  556.             case 'b': 
  557.                 breaking ^= 1; 
  558.                 note("%sbreaking after labels", breaking ? "" : "not ");
  559.                 break;
  560.             case 'n': 
  561.                 numeric_labeling ^= 1; 
  562.                 note("numeric labels %sabled", 
  563.                                         numeric_labeling ? "en" : "dis");
  564.                 break;
  565.             case 'h':
  566.                 requested_height_used = fetch_value(requested_height_used, 
  567.                                                                     .01, 1.);
  568.                 if(requested_height_used + requested_up_move > 1.)
  569.                     requested_up_move = 1. - requested_height_used;
  570.                 break;
  571.             case 'w':
  572.                 requested_width_used = fetch_value(requested_width_used, 
  573.                                                                     .01, 1.);
  574.                 if(requested_width_used + requested_right_move > 1.)
  575.                     requested_right_move = 1. - requested_width_used;
  576.                 break;
  577.             case 'u':
  578.                 requested_up_move = fetch_value(requested_up_move, 0., .99);
  579.                 if(requested_height_used + requested_up_move > 1.)
  580.                     requested_height_used = 1. - requested_up_move;
  581.                 break;
  582.             case 'r':
  583.                 requested_right_move = fetch_value(requested_right_move,
  584.                                                                     0., .99);
  585.                 if(requested_width_used + requested_right_move > 1.)
  586.                     requested_width_used = 1. - requested_right_move;
  587.                 break;
  588.             case 'q': terminate();
  589.             case 'g': adjust_grid(); break;
  590.             case 'x': adjust_limits(x, &xmin, &xmax, &logx, y); break;
  591.             case 'y': adjust_limits(y, &ymin, &ymax, &logy, x); break;
  592.             case 'z':    
  593.                 d = xmax - xmin; xmin -= d; xmax += d;
  594.                 d = ymax - ymin; ymin -= d; ymax += d;
  595.                 ungets("\033");
  596.                 break;
  597. /*
  598.             case 'd':    
  599.                 {extern int WinVis;
  600.                 sprintf(buf, "curves = %d", curves);
  601.                 WinShowString(buf, char_width, char_height, dwin);
  602.                 break;
  603.                 }
  604. */
  605.             default:;
  606.             }
  607.         }
  608. #ifndef NOMOUSE
  609.     if(mouseInstalled)
  610.         {SetEventHandler(0, MouseHandler);
  611.         HideMouseCursor();
  612.         }
  613. #endif 
  614.     (*bwin->accept)(HIDE, NULL, bwin); 
  615.     (*main_men->accept)(CLEAR, NULL, main_men);
  616.     if(dwin->vis) (*dwin->accept)(CLEAR, NULL, dwin);
  617.     if(qwin->vis) (*qwin->accept)(CLEAR, NULL, qwin);
  618. /*
  619.     clear_graphics();
  620. */
  621. }
  622.  
  623. adjust_label()
  624. {    char *malloc();
  625.  
  626.     if(!text_labeling)
  627.         {
  628.         text_label = malloc(80);
  629.         if(!text_label) {terminate();}
  630.         text_labeling = 1;
  631.         text_label[0] = 0;
  632.         }
  633.     WinGetString("label?", text_label, 0, char_width, 2*char_height, qwin);
  634. }
  635.  
  636. BUTTON f_strings[] = 
  637. {
  638.     {" output", "o", "o"},    /*     "write both format and data file names" */
  639.     {" format", "f", "f"},    /*   "write format only" */
  640.     {" data", "d", "d"},        /*     "write data file names only" */
  641.     {" input", "i", "i"},        /*     "read format from script file", */
  642.     {0}
  643. };
  644.  
  645. script_file(argcp, argvp) int *argcp; char ***argvp;
  646. {
  647.     int c, ch, i, output_format, output_data_file_names, paramc, error;
  648.     FILE *sfile;
  649.     char **paramsp;
  650.     double min, max;
  651.     static char *params[2] = {"-f", ""};
  652.  
  653.     c = MenuResponse(f_men);
  654.     if(c == 'i')
  655.         {do
  656.             {
  657.             strcpy(buf2, default_script_file);
  658.             ch = WinGetString("file name? ", buf2, 0, char_width, 2*char_height, 
  659.                                                                     qwin);
  660.             (*qwin->accept)(CLEAR, NULL, qwin);
  661.             if(ch != 0x0d) break;
  662.                                 /* reset to initial conditions */
  663.             breaking = equal = default_labeling = dividing_by_pi = labels = 
  664.                                             magnitude = numstyles = phase = 
  665.                                             text_labeling = transposing = 0;
  666.             grid_width = grid_style = numeric_labeling = 1;
  667.             requested_rlx = requested_rly = 6;
  668.             requested_rtx = requested_rty = 30;
  669.             requested_height_used = requested_width_used = 1.;
  670.             requested_right_move = requested_up_move = 0.;
  671.             params[1]=buf2;
  672.             paramsp = params;
  673.             paramc = 2;
  674.             if(error = parse_args(¶mc, ¶msp))
  675.                 {if(dwin->vis) (*dwin->accept)(CLEAR, NULL, dwin);
  676.                 WinShowString(buf, char_width, char_height, dwin);
  677.                 }
  678.             } while(error);
  679.         }
  680.     else if(c == 'o' || c == 'f' || c == 'd')
  681.         {
  682.         output_format = (c == 'o' || c == 'f');
  683.         output_data_file_names = (c == 'o' || c == 'd');
  684.         strcpy(buf, default_script_file);
  685.         ch = WinGetString("file name? ", buf, 0, char_width, 2*char_height, qwin);
  686.         (*qwin->accept)(CLEAR, NULL, qwin);
  687.         if(ch == 0x0d)
  688.             {unlink(buf);
  689.             sfile = fopen(buf, "w");
  690.             if(sfile == 0) note("cannot open %s", buf);
  691.             else
  692.                 {
  693.                 if(output_data_file_names)
  694.                     {for (i = 0; i < *argcp; i++) 
  695.                         fprintf(sfile, "%s ", (*argvp)[i]);
  696.                     fprintf(sfile, "\n");
  697.                     }
  698.                 if(output_format)
  699.                     {
  700.                     if(automatic_abscissas)
  701.                         fprintf(sfile, "-a %g %g ", abscissa_step, abscissa_start);
  702.                     if(breaking) fprintf(sfile, "-b ");
  703.                     if(!numeric_labeling) fprintf(sfile, "-n ");
  704.                     if(default_labeling) fprintf(sfile, "-c %s ", default_label);
  705.                     if(equal) fprintf(sfile, "-e ");
  706.                     if(requested_width_used != 1.) 
  707.                         fprintf(sfile, "-w %5.3f ", requested_width_used);
  708.                     if(requested_right_move != 0.)
  709.                         fprintf(sfile, "-r %5.3f ", requested_right_move);
  710.                     if(requested_height_used != 1.) 
  711.                         fprintf(sfile, "-h %5.3f ", requested_height_used);
  712.                     if(requested_up_move != 0.)
  713.                         fprintf(sfile, "-u %5.3f ", requested_up_move);
  714.                     fprintf(sfile, "-g %d %d %d\n", grid_style, requested_rtx/requested_rlx, 
  715.                                                                 grid_width);
  716.                     if(text_labeling) fprintf(sfile, "-l \"%s\"\n", text_label);
  717.  
  718.                     if(numstyles)
  719.                         {fprintf(sfile, "-m");
  720.                         for (i=0; i<numstyles; i++)
  721.                             {show_style(buf, repeat[i], style[i]);
  722.                             fprintf(sfile, " %s", buf);
  723.                             if((i&7) == 7 || i == numstyles - 1) 
  724.                                 fprintf(sfile, "\n");
  725.                             }
  726.                         }
  727.  
  728.                     if(transposing) 
  729.                         {fprintf(sfile, "-t "); 
  730.                         min = ymin; max = ymax;
  731.                         }
  732.                     else {min = xmin; max = xmax;}
  733.                     if(logx) {min = exp10(min); max = exp10(max);}
  734.                     fprintf(sfile, "-x%s %2.4g %2.4g ", 
  735.                                               logx ? "l" : "", 
  736.                                                     min, max);
  737.  
  738.                     if(transposing) {min = xmin; max = xmax;}
  739.                     else {min = ymin; max = ymax;}
  740.                     if(logy) {min = exp10(min); max = exp10(max);}
  741.                     fprintf(sfile, "\n-y%s%s%s%s %2.4g %2.4g\n", 
  742.                                               logy ? "l" : "", 
  743.                                          magnitude ? "m" : "",
  744.                                              phase ? "p" : "",
  745.                                     dividing_by_pi ? "p" : "",
  746.                                                     min, max);
  747.                     fclose(sfile);
  748.                     }
  749.                 }
  750.             }
  751.         }
  752.     (*f_men->accept)(CLEAR, NULL, f_men);
  753. }
  754.     
  755.  
  756. BUTTON g_strings[] = 
  757. {
  758.     {" grid       +-", "g", "g"},    /*     "show/eliminate grid (toggle)", */
  759.     {" tics", "t", "t"},            /*     "tic marks per numerical label", */
  760.     {" full       +-", "f", "f"},    /*     "full grid or tic marks only (toggle)", */
  761.     {" inside     +-", "i", "i"},    /*     "tic marks on inside or outside (toggle)", */
  762.     {" 2 sides", "2", "2"},            /*     "show axes on only two sides", */
  763.     {" 4 sides", "4", "4"},            /*     "show axes on all four sides", */
  764.     {" separation +-", "s", "s"},    /*     "separate axes from graph", */
  765.     {" width", "w", "w"},            /*     "grid line width", */
  766.     {0}
  767. };
  768.  
  769. adjust_grid()
  770. {    int c;
  771.     static int toggle_separation[] = {-1, -4, -4, -4, 0, 4, 4, 4, 1};
  772.     static int to_four_sides[] = {-1, -1, -1, -1, 0, 1, 2, 1, 1};
  773.     
  774.     c = MenuResponse(g_men);
  775.         {switch(c)
  776.             {case 'g': 
  777.                 if(grid_style) grid_style = 0; else grid_style = 1; 
  778.                 note("grid %sabled", grid_style?"en":"dis");
  779.                 break;
  780.             case 'i':    
  781.                 grid_style *= -1; 
  782.                 if(grid_style)
  783.                     note("tic marks %sside", grid_style<0 ? "out" : "in");
  784.                 else
  785.                     note("(grid is disabled)");
  786.                 break;
  787.             case '2':    
  788.                 grid_style = (grid_style<0)?-3:3; 
  789.                 note("axes on 2 sides", "");
  790.                 break;
  791.             case '4':    
  792.                     /* before:    -4 -3 -2 -1 0 1 2 3 4
  793.                         after:    -1 -1 -1 -1 0 1 2 1 1    */
  794.                 grid_style = to_four_sides[grid_style - MIN_GRID_STYLE];
  795.                 note("axes on 4 sides", "");
  796.                 break;
  797.             case 'f':
  798.                 if(abs(grid_style) == 2) 
  799.                     {grid_style = 1;
  800.                     note("tic marks", "");
  801.                     }
  802.                 else 
  803.                     {grid_style = 2;
  804.                     note("full grid", "");
  805.                     }
  806.                 break;
  807.             case 's':
  808.                     /* before:    -4 -3 -2 -1 0 1 2 3 4
  809.                         after:    -1 -4 -4 -4 0 4 4 4 1    */
  810.                 grid_style = toggle_separation[grid_style - MIN_GRID_STYLE];
  811.                 note("grid %sseparated", abs(grid_style) > 3 ? "" : "not ");
  812.                 break;
  813.             case 't':    
  814.                 requested_rtx = requested_rty = requested_rlx*
  815.                     (int)fetch_value((double)requested_rtx/requested_rlx, 
  816.                                                                     1., 10.);
  817.                 break;
  818.             case 'w':    
  819.                 grid_width = (int)fetch_value((double)grid_width, 1., 7.);
  820.                 break;
  821.             }
  822.         }
  823.     (*g_men->accept)(CLEAR, NULL, g_men);
  824. }
  825.     
  826. /*            For parallel projection, the transformation is...
  827.  
  828.     (rot11 rot12 rot13 rot14)  (x)
  829.     (rot21 rot22 rot23 rot24)  (y)
  830.                                (z)
  831.                                (1)
  832. */
  833. #ifndef NOMOUSE
  834. void adjust_window(msg, data, pw) MESSAGE msg; int *data; WINDOW *pw;
  835. {    int t;
  836.     double x1, x2, y1, y2, wxmin, wxmax, wymin, wymax;
  837.  
  838.     inquire_window(&wxmin, &wxmax, &wymin, &wymax);
  839.  
  840.     if(msg == DRAG) 
  841.         {
  842.         x2 = (data[0] - rot14)/rot11;
  843.         y2 = (data[1] - rot24)/rot22;
  844.         x1 = (data[2] - rot14)/rot11;
  845.         y1 = (data[3] - rot24)/rot22;
  846.         if(x2 < .99*wxmin + .01*wxmax)        /* enlarge to left */
  847.             xmin -= (xmax - xmin);
  848.         else if(x2 > .01*wxmin + .99*wxmax)    /* enlarge to right */
  849.             xmax += (xmax - xmin);
  850.         else if(y2 < .99*wymin + .01*wymax)    /* enlarge downwards */
  851.             ymin -= (ymax - ymin);
  852.         else if(y2 > .01*wymin + .99*wymax)    /* enlarge upwards */
  853.             ymax += (ymax - ymin);
  854.         else                                /* shrink */
  855.             {if(x1 < x2) {xmin = x1; xmax = x2;}
  856.             else {xmin = x2; xmax = x1;}
  857.             if(y1 < y2) {ymin = y1; ymax = y2;}
  858.             else {ymin = y2; ymax = y1;}
  859.             }
  860. /*
  861.         sprintf(buf, "mouse x = (%d, %d), y = (%d, %d)", data[0], data[2], data[1], data[3]);
  862.         note(buf);
  863.         getchar();
  864.         sprintf(buf, "x = (%lf, %lf), y = (%lf, %lf)", x1, x2, y1, y2);
  865.         note(buf);
  866.         getchar();
  867.         sprintf(buf, "limits x = (%lf, %lf), y = (%lf, %lf)", xmin, xmax, ymin, ymax);
  868.         note(buf);
  869.         getchar();
  870. */
  871.         ungets("\033"); 
  872.         }
  873.     else if(msg == START_DRAGGING) {}    /* do nothing */
  874.     else MsgWindow(msg, data, pw);
  875. }
  876. #endif /* NOMOUSE */
  877.  
  878. int GetEvent()
  879. {    int status, hor, ver;
  880.     while(1)
  881.         {
  882. #ifndef NOMOUSE
  883.         if(mouseInstalled)
  884.             {GetPosBut(&status, &hor, &ver);
  885.             if(status & 1) return '/';
  886.             if(status & 2) return ESC;
  887.             }
  888. #endif
  889. #ifdef __TURBOC__
  890.         if(kbhit()) return scr_ci();
  891. #else
  892.         if(_os(0xb,0)) return scr_ci();
  893. #endif
  894.         }
  895. }
  896.  
  897. MENU *CreateSubMenu(ch, child_strings, pm) 
  898. char ch; BUTTON *child_strings; MENU *pm;
  899. {    BUTTON *pb;
  900.     int x0, y0;
  901.     
  902.     for (pb = pm->pab; *(int *)pb; pb++)
  903.         if(pb->val[0] == ch)
  904.             {y0 = main_men->y + pb->y + pb->h;
  905.             x0 = main_men->x + pb->x + char_width;
  906.             return pb->pm = CreateVMenu("", child_strings, x0, y0, 0);
  907.             }
  908.         /* couldn't find the specified character
  909.              - this should make the mistake apparent */
  910.     return pm;
  911. }
  912.  
  913. init_menus()
  914. {    BUTTON *pb;
  915.     static int data[2];
  916.  
  917. #ifdef NOMOUSE
  918.     mouseInstalled = 0;
  919. #else
  920.     mouseInstalled = IsMouse();
  921. #endif
  922.  
  923.     bwin = CreateWindow("", 0, 0, 0);        /* background window */
  924.     data[0] = pixels_wide - 1;
  925.     data[1] = pixels_high - 1;
  926.     (*bwin->accept)(RESIZE, data, bwin);
  927. #ifndef NOMOUSE
  928.     bwin->accept = adjust_window;
  929. #endif
  930.     bwin->border_style = 0;        /* no border */
  931.  
  932. /*    (*bwin->accept)(REDRAW, NULL, bwin); */
  933.  
  934.     main_men = CreateVMenu("", main_strings, pixels_wide - 200, 10, 0);
  935.     pb = main_men->pab;
  936.  
  937.     x_men = CreateSubMenu('y', x_strings, main_men);
  938.     f_men = CreateSubMenu('f', f_strings, main_men);
  939.     g_men = CreateSubMenu('g', g_strings, main_men);
  940.     a_men = CreateSubMenu('a', a_strings, main_men);
  941.     s_men = CreateSubMenu('m', s_strings, main_men);
  942.  
  943. #ifndef NOMOUSE
  944.     s_men->accept = ShowStyles;
  945. #endif
  946.  
  947.     qwin = CreateWindow("", 6*char_width, 17*char_height, 0);
  948.     data[0] = 40*char_width;
  949.     data[1] = 2*char_height + 2;
  950.     (*qwin->accept)(RESIZE, data, qwin);
  951.  
  952.     dwin = CreateWindow("", 6*char_width, 20*char_height, 0);
  953.     data[0] = 40*char_width;
  954.     data[1] = char_height + 2;
  955.     (*dwin->accept)(RESIZE, data, dwin);
  956. /*
  957.     show_menu(main_men);    getchar();
  958.     show_menu(x_men);    getchar();
  959.     show_menu(f_men);    getchar();
  960.     show_menu(g_men);    getchar();
  961.     show_menu(a_men);    getchar();
  962. */
  963. }
  964.  
  965. terminate()
  966. {
  967. #ifndef NOMOUSE
  968.     if(mouseInstalled)
  969.         {SetEventHandler(0, MouseHandler);
  970.         HideMouseCursor();
  971.         }
  972. #endif 
  973.     terminate_view_surface(1); 
  974.     exit();
  975. }
  976.