1
2 /*
3 * Copyright 1998 - 2004 Graeme W. Gill
4 * All rights reserved.
5 *
6 * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
7 * see the License.txt file for licencing details.
8 */
9
10 /* This is a simple 2d graph plotter that runs on MSWindows/OSX/X11 */
11 /* The code is in three sections, one for each GUI environment. */
12 /* (Perhaps common code could be consolidated ?) */
13
14
15 /*
16 * TTBD:
17 *
18 * Allow for a window title for each plot.
19 *
20 * Put all state information in plot_info (window handles etc.)
21 * Create thread to handle events, so it updates correctly.
22 * (Will have to lock plot info updates or ping pong them);
23 * Have call to destroy window.
24 * (Could then move to having multiple instances of plot).
25 *
26 * OS X Cocoa code doesn't get window focus. No idea why.
27 *
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #ifdef UNIX
35 #include <unistd.h>
36 #endif
37 #include <math.h>
38 #include "numlib.h"
39 #include "plot.h"
40 //#ifdef STANDALONE_TEST
41 #include "ui.h"
42 //#endif /* STANDALONE_TEST */
43
44 #undef DODEBUG /* Print error messages & progress reports */
45 //#define STANDALONE_TEST /* Defined by build script */
46
47 #define NTICK 10
48 #define LTHICK 1.2 /* Plot line thickness */
49 #define ILTHICK ((int)(LTHICK+0.5)) /* Integer line thickness */
50 //#define ILTHICK 2
51 #undef CROSSES /* Mark input points with crosses */
52
53 #define DEFWWIDTH 500
54 #define DEFWHEIGHT 500
55
56 /* Graph order is Black = Y1, Red = Y2, Green = Y3, Blue = Y4, Yellow = Y5, Purple = Y6 */
57 /* Brown = Y7, Orange = Y8, Grey = Y9, Magenta = Y10 */
58
59 double nicenum(double x, int round);
60
61 #define MXGPHS 10 /* Number of graphs with common X axis */
62
63 /* Colors of the graphs */
64 static int gcolors[MXGPHS][3] = {
65 { 0, 0, 0}, /* Black */
66 { 210, 30, 0}, /* Red */
67 { 0, 200, 90}, /* Green */
68 { 0, 10, 255}, /* Blue */
69 { 200, 200, 0}, /* Yellow */
70 { 220, 0, 255}, /* Purple */
71 { 136, 86, 68}, /* Brown */
72 { 248, 95, 0}, /* Orange */
73 { 160, 160, 160}, /* Grey */
74 { 220, 30, 220} /* Magenta */
75 };
76
77 /* Information defining plot */
78 /* There is one global instance of this. */
79 struct _plot_info {
80 void *cx; /* Other Context */
81
82 int flags; /* Flags */
83 int dowait; /* Wait for user key if > 0, wait for n secs if < 0 */
84 double ratio; /* Aspect ratio of window, X/Y */
85
86 /* Plot point information */
87 double mnx, mxx, mny, mxy; /* Extrema of values to be plotted */
88 int graph; /* NZ if graph, Z if vectors */
89 int revx; /* reversed X axis */
90
91 double *x1, *x2;
92 double *yy[MXGPHS]; /* y1 - y10 */
93 char **ntext;
94 int n;
95
96 double *x7, *y7;
97 plot_col *mcols;
98 char **mtext;
99 int m;
100
101 double *x8, *y8, *x9, *y9;
102 plot_col *ocols;
103 int o;
104
105 /* Plot instance information */
106 int sx,sy; /* Screen offset */
107 int sw,sh; /* Screen width and height */
108 double scx, scy; /* Scale from input values to screen pixels */
109
110 }; typedef struct _plot_info plot_info;
111
112 /* Global to transfer info to window callback */
113 static plot_info pd;
114
115 #define PLOTF_NONE 0x0000
116 #define PLOTF_GRAPHCROSSES 0x0001 /* Plot crosses at each point on the graphs */
117 #define PLOTF_VECCROSSES 0x0002 /* Plot crosses at the end of x1,y1 -> x2,y2 */
118
119 /* Declaration of superset */
120 static int do_plot_imp(
121 int flags,
122 double xmin, double xmax, double ymin, double ymax, /* Bounding box */
123 double ratio, /* Aspect ratio of window, X/Y, 1.0 = nominal */
124 int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
125 double *x1, double *x2,
126 double *yy[MXGPHS], char **ntext,
127 int n,
128 double *x7, double *y7, plot_col *mcols, char **mtext,
129 int m,
130 double *x8, double *y8, double *x9, double*y9, plot_col *ocols,
131 int o
132 );
133
134
135 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
136
137 /* Public routines */
138 /* Plot up to 3 graphs. Wait for key */
139 /* return 0 on success, -1 on error */
140 /* If n is -ve, reverse the X axis */
141 int
do_plot(double * x,double * y1,double * y2,double * y3,int n)142 do_plot(
143 double *x,
144 double *y1, /* Up to 3 graphs */
145 double *y2,
146 double *y3,
147 int n) {
148 int i, j;
149 double xmin, xmax, ymin, ymax;
150 double *yy[MXGPHS];
151
152 for (j = 0; j < MXGPHS; j++)
153 yy[j] = NULL;
154
155 yy[0] = y1;
156 yy[1] = y2;
157 yy[2] = y3;
158
159 /* Determine min and max dimensions of plot */
160 xmin = ymin = 1e6;
161 xmax = ymax = -1e6;
162
163 for (i = 0; i < n; i++) {
164 if (xmin > x[i])
165 xmin = x[i];
166 if (xmax < x[i])
167 xmax = x[i];
168
169 for (j = 0; j < MXGPHS; j++) {
170 if (yy[j] != NULL) {
171 if (ymin > yy[j][i])
172 ymin = yy[j][i];
173 if (ymax < yy[j][i])
174 ymax = yy[j][i];
175 }
176 }
177 }
178
179 /* Work out scale factors */
180 if ((xmax - xmin) == 0.0)
181 xmax += 0.5, xmin -= 0.5;
182 if ((ymax - ymin) == 0.0)
183 ymax += 0.5, ymin -= 0.5;
184
185 return do_plot_imp(PLOTF_NONE,
186 xmin, xmax, ymin, ymax, 1.0, 1,
187 x, NULL, yy, NULL, n,
188 NULL, NULL, NULL, NULL, 0,
189 NULL, NULL, NULL, NULL, NULL, 0);
190 }
191
192 /* Public routines */
193 /* Plot up to 3 graphs + crosses. Wait for key */
194 /* return 0 on success, -1 on error */
195 /* If n is -ve, reverse the X axis */
196 int
do_plot_p(double * x,double * y1,double * y2,double * y3,int n,double * x4,double * y4,int m)197 do_plot_p(
198 double *x,
199 double *y1, /* Up to 3 graphs */
200 double *y2,
201 double *y3,
202 int n,
203 double *x4, double *y4, /* And crosses */
204 int m) {
205 int i, j;
206 double xmin, xmax, ymin, ymax;
207 double *yy[MXGPHS];
208
209 for (j = 0; j < MXGPHS; j++)
210 yy[j] = NULL;
211
212 yy[0] = y1;
213 yy[1] = y2;
214 yy[2] = y3;
215
216 /* Determine min and max dimensions of plot */
217 xmin = ymin = 1e6;
218 xmax = ymax = -1e6;
219
220 for (i = 0; i < n; i++) {
221 if (xmin > x[i])
222 xmin = x[i];
223 if (xmax < x[i])
224 xmax = x[i];
225
226 for (j = 0; j < MXGPHS; j++) {
227 if (yy[j] != NULL) {
228 if (ymin > yy[j][i])
229 ymin = yy[j][i];
230 if (ymax < yy[j][i])
231 ymax = yy[j][i];
232 }
233 }
234 }
235
236 for (i = 0; i < m; i++) {
237 if (x4 != NULL) {
238 if (xmin > x4[i])
239 xmin = x4[i];
240 if (xmax < x4[i])
241 xmax = x4[i];
242 }
243 if (y4 != NULL) {
244 if (ymin > y4[i])
245 ymin = y4[i];
246 if (ymax < y4[i])
247 ymax = y4[i];
248 }
249 }
250
251 /* Work out scale factors */
252 if ((xmax - xmin) == 0.0)
253 xmax += 0.5, xmin -= 0.5;
254 if ((ymax - ymin) == 0.0)
255 ymax += 0.5, ymin -= 0.5;
256
257 return do_plot_imp(PLOTF_NONE,
258 xmin, xmax, ymin, ymax, 1.0, 1,
259 x, NULL, yy, NULL, n,
260 x4, y4, NULL, NULL, m ,
261 NULL, NULL, NULL, NULL, NULL, 0);
262 }
263
264 /* Plot up to 3 graphs with specified window size. */
265 /* if dowait > 0, wait for user key */
266 /* if dowait < 0, wait for no seconds */
267 /* If xmax > xmin, use as x scale, else auto. */
268 /* If ymax > ymin, use as y scale, else auto. */
269 /* ratio is window X / Y */
270 /* return 0 on success, -1 on error */
271 /* If n is -ve, reverse the X axis */
272 int
do_plot_x(double * x,double * y1,double * y2,double * y3,int n,int dowait,double pxmin,double pxmax,double pymin,double pymax,double ratio)273 do_plot_x(
274 double *x,
275 double *y1,
276 double *y2,
277 double *y3,
278 int n,
279 int dowait,
280 double pxmin,
281 double pxmax,
282 double pymin,
283 double pymax,
284 double ratio
285 ) {
286 int i, j;
287 double xmin, xmax, ymin, ymax;
288 double *yy[MXGPHS];
289
290 for (j = 0; j < MXGPHS; j++)
291 yy[j] = NULL;
292
293 yy[0] = y1;
294 yy[1] = y2;
295 yy[2] = y3;
296
297 /* Determine min and max dimensions of plot */
298 xmin = ymin = 1e6;
299 xmax = ymax = -1e6;
300
301 for (i = 0; i < n; i++) {
302 if (xmin > x[i])
303 xmin = x[i];
304 if (xmax < x[i])
305 xmax = x[i];
306
307 for (j = 0; j < MXGPHS; j++) {
308 if (yy[j] != NULL) {
309 if (ymin > yy[j][i])
310 ymin = yy[j][i];
311 if (ymax < yy[j][i])
312 ymax = yy[j][i];
313 }
314 }
315 }
316
317 /* Work out scale factors */
318 if ((xmax - xmin) == 0.0)
319 xmax += 0.5, xmin -= 0.5;
320 if ((ymax - ymin) == 0.0)
321 ymax += 0.5, ymin -= 0.5;
322
323 if (pxmax > pxmin) {
324 xmax = pxmax;
325 xmin = pxmin;
326 }
327 if (pymax > pymin) {
328 ymax = pymax;
329 ymin = pymin;
330 }
331
332 return do_plot_imp(PLOTF_NONE,
333 xmin, xmax, ymin, ymax, ratio, dowait,
334 x, NULL, yy, NULL, n,
335 NULL, NULL, NULL, NULL, 0,
336 NULL, NULL, NULL, NULL, NULL, 0);
337 }
338
339 /* Public routines */
340 /* Plot up to 6 graphs. Wait for a key */
341 /* return 0 on success, -1 on error */
342 /* If n is -ve, reverse the X axis */
343 int
do_plot6(double * x,double * y1,double * y2,double * y3,double * y4,double * y5,double * y6,int n)344 do_plot6(
345 double *x, /* X coord */
346 double *y1, /* Black */
347 double *y2, /* Red */
348 double *y3, /* Green */
349 double *y4, /* Blue */
350 double *y5, /* Yellow */
351 double *y6, /* Purple */
352 int n) { /* Number of values */
353 int i, j;
354 double xmin, xmax, ymin, ymax;
355 int nn = abs(n);
356 double *yy[MXGPHS];
357
358 for (j = 0; j < MXGPHS; j++)
359 yy[j] = NULL;
360
361 yy[0] = y1;
362 yy[1] = y2;
363 yy[2] = y3;
364 yy[3] = y4;
365 yy[4] = y5;
366 yy[5] = y6;
367
368 /* Determine min and max dimensions of plot */
369 xmin = ymin = 1e6;
370 xmax = ymax = -1e6;
371
372 for (i = 0; i < nn; i++) {
373 if (xmin > x[i])
374 xmin = x[i];
375 if (xmax < x[i])
376 xmax = x[i];
377
378 for (j = 0; j < MXGPHS; j++) {
379 if (yy[j] != NULL) {
380 if (ymin > yy[j][i])
381 ymin = yy[j][i];
382 if (ymax < yy[j][i])
383 ymax = yy[j][i];
384 }
385 }
386 }
387
388 /* Work out scale factors */
389 if ((xmax - xmin) == 0.0)
390 xmax += 0.5, xmin -= 0.5;
391 if ((ymax - ymin) == 0.0)
392 ymax += 0.5, ymin -= 0.5;
393
394 return do_plot_imp(PLOTF_NONE,
395 xmin, xmax, ymin, ymax, 1.0, 1,
396 x, NULL, yy, NULL, n,
397 NULL, NULL, NULL, NULL, n ,
398 NULL, NULL, NULL, NULL, NULL, 0);
399 }
400
401 /* Public routines */
402 /* Plot up to 6 graphs + optional crosses. Wait for a key */
403 /* return 0 on success, -1 on error */
404 /* If n is -ve, reverse the X axis */
405 int
do_plot6p(double * x,double * y1,double * y2,double * y3,double * y4,double * y5,double * y6,int n,double * xp,double * yp,int m)406 do_plot6p(
407 double *x, /* X coord */
408 double *y1, /* Black */
409 double *y2, /* Red */
410 double *y3, /* Green */
411 double *y4, /* Blue */
412 double *y5, /* Yellow */
413 double *y6, /* Purple */
414 int n, /* Number of values */
415 double *xp, double *yp, /* And crosses */
416 int m) {
417 int i, j;
418 double xmin, xmax, ymin, ymax;
419 int nn = abs(n);
420 double *yy[MXGPHS];
421
422 for (j = 0; j < MXGPHS; j++)
423 yy[j] = NULL;
424
425 yy[0] = y1;
426 yy[1] = y2;
427 yy[2] = y3;
428 yy[3] = y4;
429 yy[4] = y5;
430 yy[5] = y6;
431
432 /* Determine min and max dimensions of plot */
433 xmin = ymin = 1e6;
434 xmax = ymax = -1e6;
435
436 for (i = 0; i < nn; i++) {
437 if (xmin > x[i])
438 xmin = x[i];
439 if (xmax < x[i])
440 xmax = x[i];
441
442 for (j = 0; j < MXGPHS; j++) {
443 if (yy[j] != NULL) {
444 if (ymin > yy[j][i])
445 ymin = yy[j][i];
446 if (ymax < yy[j][i])
447 ymax = yy[j][i];
448 }
449 }
450 }
451
452 for (i = 0; i < m; i++) {
453 if (xp != NULL) {
454 if (xmin > xp[i])
455 xmin = xp[i];
456 if (xmax < xp[i])
457 xmax = xp[i];
458 }
459 if (yp != NULL) {
460 if (ymin > yp[i])
461 ymin = yp[i];
462 if (ymax < yp[i])
463 ymax = yp[i];
464 }
465 }
466
467 /* Work out scale factors */
468 if ((xmax - xmin) == 0.0)
469 xmax += 0.5, xmin -= 0.5;
470 if ((ymax - ymin) == 0.0)
471 ymax += 0.5, ymin -= 0.5;
472
473 return do_plot_imp(PLOTF_NONE,
474 xmin, xmax, ymin, ymax, 1.0, 1,
475 x, NULL, yy, NULL, n,
476 xp, yp, NULL, NULL, m,
477 NULL, NULL, NULL, NULL, NULL, 0);
478 }
479
480 /* Public routines */
481 /* Plot up to 10 graphs. Wait for a key */
482 /* return 0 on success, -1 on error */
483 /* If n is -ve, reverse the X axis */
484 int
do_plot10(double * x,double * y1,double * y2,double * y3,double * y4,double * y5,double * y6,double * y7,double * y8,double * y9,double * y10,int n,int zero)485 do_plot10(
486 double *x, /* X coord */
487 double *y1, /* Black */
488 double *y2, /* Red */
489 double *y3, /* Green */
490 double *y4, /* Blue */
491 double *y5, /* Yellow */
492 double *y6, /* Purple */
493 double *y7, /* Brown */
494 double *y8, /* Orange */
495 double *y9, /* Grey */
496 double *y10,/* White */
497 int n, /* Number of values */
498 int zero /* Flag - make sure zero is in y range */
499 ) {
500 int i, j;
501 double xmin, xmax, ymin, ymax;
502 int nn = abs(n);
503 double *yy[MXGPHS];
504
505 for (j = 0; j < MXGPHS; j++)
506 yy[j] = NULL;
507
508 yy[0] = y1;
509 yy[1] = y2;
510 yy[2] = y3;
511 yy[3] = y4;
512 yy[4] = y5;
513 yy[5] = y6;
514 yy[6] = y7;
515 yy[7] = y8;
516 yy[8] = y9;
517 yy[9] = y10;
518
519 /* Determine min and max dimensions of plot */
520 xmin = ymin = 1e6;
521 xmax = ymax = -1e6;
522
523 for (i = 0; i < n; i++) {
524 if (xmin > x[i])
525 xmin = x[i];
526 if (xmax < x[i])
527 xmax = x[i];
528
529 for (j = 0; j < MXGPHS; j++) {
530 if (yy[j] != NULL) {
531 if (ymin > yy[j][i])
532 ymin = yy[j][i];
533 if (ymax < yy[j][i])
534 ymax = yy[j][i];
535 }
536 }
537 }
538
539 if (zero && ymin > 0.0)
540 ymin = 0.0;
541
542 /* Work out scale factors */
543 if ((xmax - xmin) == 0.0)
544 xmax += 0.5, xmin -= 0.5;
545 if ((ymax - ymin) == 0.0)
546 ymax += 0.5, ymin -= 0.5;
547
548 return do_plot_imp(PLOTF_NONE,
549 xmin, xmax, ymin, ymax, 1.0, 1,
550 x, NULL, yy, NULL, n,
551 NULL, NULL, NULL, NULL, n ,
552 NULL, NULL, NULL, NULL, NULL, 0);
553 }
554
555 /* Public routines */
556 /* Plot up to 10 graphs + optional crosses. Wait for a key */
557 /* return 0 on success, -1 on error */
558 /* If n is -ve, reverse the X axis */
559 int
do_plot10p(double * x,double * y1,double * y2,double * y3,double * y4,double * y5,double * y6,double * y7,double * y8,double * y9,double * y10,int n,double * xp,double * yp,int m)560 do_plot10p(
561 double *x, /* X coord */
562 double *y1, /* Black */
563 double *y2, /* Red */
564 double *y3, /* Green */
565 double *y4, /* Blue */
566 double *y5, /* Yellow */
567 double *y6, /* Purple */
568 double *y7, /* Brown */
569 double *y8, /* Orange */
570 double *y9, /* Grey */
571 double *y10,/* White */
572 int n, /* Number of values */
573 double *xp, double *yp, /* And crosses */
574 int m) {
575 int i, j;
576 double xmin, xmax, ymin, ymax;
577 int nn = abs(n);
578 double *yy[MXGPHS];
579
580 for (j = 0; j < MXGPHS; j++)
581 yy[j] = NULL;
582
583 yy[0] = y1;
584 yy[1] = y2;
585 yy[2] = y3;
586 yy[3] = y4;
587 yy[4] = y5;
588 yy[5] = y6;
589 yy[6] = y7;
590 yy[7] = y8;
591 yy[9] = y9;
592 yy[5] = y10;
593
594 /* Determine min and max dimensions of plot */
595 xmin = ymin = 1e6;
596 xmax = ymax = -1e6;
597
598 for (i = 0; i < n; i++) {
599 if (xmin > x[i])
600 xmin = x[i];
601 if (xmax < x[i])
602 xmax = x[i];
603
604 for (j = 0; j < MXGPHS; j++) {
605 if (yy[j] != NULL) {
606 if (ymin > yy[j][i])
607 ymin = yy[j][i];
608 if (ymax < yy[j][i])
609 ymax = yy[j][i];
610 }
611 }
612 }
613
614 for (i = 0; i < m; i++) {
615 if (xp != NULL) {
616 if (xmin > xp[i])
617 xmin = xp[i];
618 if (xmax < xp[i])
619 xmax = xp[i];
620 }
621 if (yp != NULL) {
622 if (ymin > yp[i])
623 ymin = yp[i];
624 if (ymax < yp[i])
625 ymax = yp[i];
626 }
627 }
628
629 /* Work out scale factors */
630 if ((xmax - xmin) == 0.0)
631 xmax += 0.5, xmin -= 0.5;
632 if ((ymax - ymin) == 0.0)
633 ymax += 0.5, ymin -= 0.5;
634
635 return do_plot_imp(PLOTF_NONE,
636 xmin, xmax, ymin, ymax, 1.0, 1,
637 x, NULL, yy, NULL, n,
638 xp, yp, NULL, NULL, m,
639 NULL, NULL, NULL, NULL, NULL, 0);
640 }
641
642
643 /* Plot a bunch of vectors + optional crosses */
644 /* return 0 on success, -1 on error */
do_plot_vec(double xmin,double xmax,double ymin,double ymax,double * x1,double * y1,double * x2,double * y2,int n,int dowait,double * x3,double * y3,plot_col * mcols,char ** mtext,int m)645 int do_plot_vec(
646 double xmin,
647 double xmax,
648 double ymin,
649 double ymax,
650 double *x1, /* vector start */
651 double *y1,
652 double *x2, /* vector end */
653 double *y2,
654 int n, /* Number of vectors */
655 int dowait,
656 double *x3, /* extra point */
657 double *y3,
658 plot_col *mcols, /* point colors */
659 char **mtext, /* notation */
660 int m /* Number of points */
661 ) {
662 int j;
663 double *yy[MXGPHS];
664
665 for (j = 0; j < MXGPHS; j++)
666 yy[j] = NULL;
667
668 yy[0] = y1;
669 yy[1] = y2;
670
671 return do_plot_imp(PLOTF_VECCROSSES,
672 xmin, xmax, ymin, ymax, 1.0, dowait,
673 x1, x2, yy, NULL, n,
674 x3, y3, mcols, mtext, m,
675 NULL, NULL, NULL, NULL, NULL, 0);
676 }
677
678 /* Plot a bunch of vectors & crosses + optional crosses + optional vectors*/
679 /* return 0 on success, -1 on error */
do_plot_vec2(double xmin,double xmax,double ymin,double ymax,double * x1,double * y1,double * x2,double * y2,char ** ntext,int n,int dowait,double * x3,double * y3,plot_col * mcols,char ** mtext,int m,double * x4,double * y4,double * x5,double * y5,plot_col * ocols,int o)680 int do_plot_vec2(
681 double xmin,
682 double xmax,
683 double ymin,
684 double ymax,
685 double *x1, /* n vector start */
686 double *y1,
687 double *x2, /* vector end and diagonal cross */
688 double *y2,
689 char **ntext, /* text annotation at cross */
690 int n, /* Number of vectors */
691 int dowait,
692 double *x3, /* m extra crosses */
693 double *y3,
694 plot_col *mcols,/* cross colors */
695 char **mtext, /* text annotation at cross */
696 int m, /* Number of crosses */
697 double *x4, /* o vector start */
698 double *y4,
699 double *x5, /* o vector end */
700 double *y5,
701 plot_col *ocols,/* Vector colors */
702 int o /* Number of vectors */
703 ) {
704 int j;
705 double *yy[MXGPHS];
706
707 for (j = 0; j < MXGPHS; j++)
708 yy[j] = NULL;
709
710 yy[0] = y1;
711 yy[1] = y2;
712
713 return do_plot_imp(PLOTF_VECCROSSES,
714 xmin, xmax, ymin, ymax, 1.0, dowait,
715 x1, x2, yy, ntext, n,
716 x3, y3, mcols, mtext, m,
717 x4, y4, x5, y5, ocols, o);
718 }
719
720 /* ********************************** NT version ********************** */
721 #ifdef NT
722
723 #include <windows.h>
724
725 #ifdef DODEBUG
726 # define debugf(xx) printf xx
727 #else
728 # define debugf(xx)
729 #endif
730
731 double plot_ratio = 1.0;
732 HANDLE plot_th; /* Thread */
733 char plot_AppName[] = "PlotWin";
734 HWND plot_hwnd = NULL; /* Open only one window per session */
735 int plot_signal = 0; /* Signal a key or quit */
736
737 static LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);
738
739 /* Thread to handle message processing, so that there is no delay */
740 /* when the main thread is doing other things. */
plot_message_thread(LPVOID lpParameter)741 DWORD WINAPI plot_message_thread(LPVOID lpParameter) {
742 MSG msg;
743 WNDCLASS wc;
744 ATOM arv;
745 HWND _hwnd;
746
747 // Fill in window class structure with parameters that describe the
748 // main window.
749
750 wc.style = CS_HREDRAW | CS_VREDRAW; // Class style(s).
751 wc.lpfnWndProc = MainWndProc; // Function to retrieve messages for windows of this class.
752 wc.cbClsExtra = 0; // No per-class extra data.
753 wc.cbWndExtra = 0; // No per-window extra data.
754 wc.hInstance = NULL; // Application that owns the class.
755 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
756 wc.hCursor = LoadCursor(NULL, IDC_CROSS);
757 wc.hbrBackground = GetStockObject(WHITE_BRUSH);
758 wc.lpszMenuName = NULL;
759 wc.lpszClassName = plot_AppName;
760
761 arv = RegisterClass(&wc);
762
763 if (!arv) {
764 debugf(("RegisterClass failed, lasterr = %d\n",GetLastError()));
765 return -1;
766 }
767
768 _hwnd = CreateWindow(
769 plot_AppName,
770 "2D Diagnostic Graph Plot",
771 WS_OVERLAPPEDWINDOW,
772 CW_USEDEFAULT,
773 CW_USEDEFAULT,
774 (int)(DEFWWIDTH * plot_ratio + 0.5),
775 DEFWHEIGHT,
776 NULL,
777 NULL,
778 NULL, // hInstance,
779 NULL);
780
781 if (!_hwnd) {
782 debugf(("CreateWindow failed, lasterr = %d\n",GetLastError()));
783 return -1;
784 }
785
786 ShowWindow(_hwnd, SW_SHOW);
787
788 plot_hwnd = _hwnd;
789
790 /* Now process messages until we're done */
791 for (;;) {
792 if (GetMessage(&msg, NULL, 0, 0)) {
793 TranslateMessage(&msg);
794 DispatchMessage(&msg);
795 if (plot_signal == 99)
796 break;
797 }
798 }
799
800 if (UnregisterClass(plot_AppName, NULL) == 0) {
801 debugf(("UnregisterClass failed, lasterr = %d\n",GetLastError()));
802 }
803
804 plot_hwnd = NULL; /* Signal it's been deleted */
805
806 return 0;
807 }
808
809 /* Superset implementation function: */
810 /* return 0 on success, -1 on error */
811 /* Hybrid Graph uses x1 : y1, y2, y3, y4, y5, y6 for up to 6 graph curves + */
812 /* optional diagonal crosses at x7, y7 in yellow (x2 == NULL). */
813 /* Vector uses x1, y1 to x2, y2 as a vector with a (optional) diagonal cross at x2, y2 */
814 /* all in black with annotation ntext at the cross, */
815 /* plus a (optiona) diagonal cross at x7, y7 in yellow. The color for x7, y7 can be */
816 /* overidden by an array of colors mcols, plus optional label text mtext. (x2 != NULL) */
817 /* n = number of points/vectors. -ve for reversed X axis */
818 /* m = number of extra points (x2,y3 or x7,y7) */
819 /* x8,y8 to x9,y9 are extra optional vectors with optional colors */
do_plot_imp(int flags,double xmin,double xmax,double ymin,double ymax,double ratio,int dowait,double * x1,double * x2,double * yy[MXGPHS],char ** ntext,int n,double * x7,double * y7,plot_col * mcols,char ** mtext,int m,double * x8,double * y8,double * x9,double * y9,plot_col * ocols,int o)820 static int do_plot_imp(
821 int flags,
822 double xmin, double xmax, double ymin, double ymax, /* Bounding box */
823 double ratio, /* Aspect ratio of window, X/Y */
824 int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
825 double *x1, double *x2,
826 double *yy[MXGPHS], char **ntext,
827 int n,
828 double *x7, double *y7, plot_col *mcols, char **mtext,
829 int m,
830 double *x8, double *y8, double *x9, double*y9, plot_col *ocols,
831 int o
832 ) {
833 pd.flags = flags;
834 pd.dowait = 10 * dowait;
835 pd.ratio = ratio;
836 {
837 int j;
838 double xr,yr;
839
840 pd.mnx = xmin;
841 pd.mny = ymin;
842 pd.mxx = xmax;
843 pd.mxy = ymax;
844
845 /* Allow some extra around plot */
846 xr = pd.mxx - pd.mnx;
847 yr = pd.mxy - pd.mny;
848 if (xr < 1e-6)
849 xr = 1e-6;
850 if (yr < 1e-6)
851 yr = 1e-6;
852 pd.mnx -= xr/10.0;
853 pd.mxx += xr/10.0;
854 pd.mny -= yr/10.0;
855 pd.mxy += yr/10.0;
856
857 /* Transfer raw point info */
858 if (x2 == NULL)
859 pd.graph = 1; /* 6 graphs + points */
860 else
861 pd.graph = 0;
862 pd.x1 = x1;
863 pd.x2 = x2;
864 for (j = 0; j < MXGPHS; j++)
865 pd.yy[j] = yy[j];
866 pd.ntext = ntext;
867 pd.n = abs(n);
868
869 if (n < 0) {
870 double tt;
871 tt = pd.mxx;
872 pd.mxx = pd.mnx;
873 pd.mnx = tt;
874 pd.revx = 1;
875 } else {
876 pd.revx = 0;
877 }
878 pd.x7 = x7;
879 pd.y7 = y7;
880 pd.mcols = mcols;
881 pd.mtext = mtext;
882 pd.m = abs(m);
883
884 pd.x8 = x8;
885 pd.y8 = y8;
886 pd.x9 = x9;
887 pd.y9 = y9;
888 pd.ocols = ocols;
889 pd.o = abs(o);
890 }
891
892 /* ------------------------------------------- */
893 /* Setup windows stuff */
894 {
895 ui_UsingGUI();
896
897 /* It would be nice to reduce number of globals. */
898
899 /* We don't clean up properly either - ie. don't delete thread etc. */
900
901 /* Create thread that creats window and processes window messages */
902 if (plot_hwnd == NULL) {
903
904 plot_ratio = ratio;
905
906 plot_th = CreateThread(NULL, 0, plot_message_thread, NULL, 0, NULL);
907 if (plot_th == NULL) {
908 debugf(("new_athread failed\n"));
909 return -1;
910 }
911 while (plot_hwnd == NULL)
912 Sleep(50);
913
914 SetForegroundWindow(plot_hwnd); /* Raise */
915 }
916
917 plot_signal = 0;
918
919 if (dowait > 0)
920 SetForegroundWindow(plot_hwnd); /* Raise */
921
922 /* Force a repaint with the new data */
923 if (!InvalidateRgn(plot_hwnd,NULL,TRUE)) {
924 debugf(("InvalidateRgn failed, lasterr = %d\n",GetLastError()));
925 return -1;
926 }
927
928 if (dowait > 0) { /* Wait for a space key */
929 while(plot_signal == 0 && plot_hwnd != NULL)
930 Sleep(50);
931 plot_signal = 0;
932 } else if (dowait < 0) {
933 Sleep(-dowait * 1000);
934 }
935 }
936 return 0;
937 }
938
939 void DoPlot(HDC hdc, plot_info *pd);
940
MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)941 static LRESULT CALLBACK MainWndProc(
942 HWND hwnd,
943 UINT message,
944 WPARAM wParam,
945 LPARAM lParam
946 ) {
947 HDC hdc;
948 PAINTSTRUCT ps;
949 RECT rect;
950
951 debugf(("Handling message type 0x%x\n",message));
952 // Could use Set/GetWindowLong() to pass window class info instead of global pd (beware NULL)
953 switch(message) {
954 case WM_PAINT:
955 debugf(("It's a paint message\n"));
956 hdc = BeginPaint(hwnd, &ps);
957 GetClientRect(hwnd, &rect);
958
959 /* Setup the plot info structure for this drawing */
960 pd.sx = rect.left;
961 pd.sy = rect.top;
962 pd.sw = 1 + rect.right - rect.left;
963 pd.sh = 1 + rect.bottom - rect.top;
964 pd.scx = (pd.sw - 10)/(pd.mxx - pd.mnx);
965 pd.scy = (pd.sh - 10)/(pd.mxy - pd.mny);
966
967 DoPlot(hdc, &pd);
968
969 EndPaint(hwnd, &ps);
970
971 return 0;
972
973 case WM_CHAR:
974 debugf(("It's a char message, wParam = 0x%x\n",wParam));
975 switch(wParam) {
976 case '\r':
977 case '\n':
978 case ' ': /* Space */
979 debugf(("It's a SPACE, so signal it\n"));
980 plot_signal = 1;
981 return 0;
982 }
983
984 case WM_CLOSE:
985 debugf(("It's a close message\n"));
986 DestroyWindow(hwnd);
987 return 0;
988
989 case WM_DESTROY:
990 debugf(("It's a destroy message\n"));
991 plot_signal = 99;
992 PostQuitMessage(0);
993 return 0;
994 }
995
996 debugf(("It's a message not handled here\n"));
997 return DefWindowProc(hwnd, message, wParam, lParam);
998 }
999
1000 void
xtick(HDC hdc,plot_info * pdp,double x,char * lab)1001 xtick(HDC hdc, plot_info *pdp, double x, char *lab)
1002 {
1003 int xx,yy;
1004 RECT rct;
1005
1006 xx = 10 + (int)((x - pdp->mnx) * pdp->scx + 0.5);
1007 yy = pdp->sh - 10;
1008
1009 MoveToEx(hdc,xx, yy, NULL);
1010 LineTo( hdc,xx, 0);
1011 rct.right =
1012 rct.left = xx;
1013 rct.top =
1014 rct.bottom = yy;
1015 DrawText(hdc, lab, -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
1016 }
1017
1018 void
ytick(HDC hdc,plot_info * pdp,double y,char * lab)1019 ytick(HDC hdc, plot_info *pdp, double y, char *lab)
1020 {
1021 int xx,yy;
1022 RECT rct;
1023
1024 xx = 5;
1025 yy = pdp->sh - 10 - (int)((y - pdp->mny) * pdp->scy + 0.5);
1026 MoveToEx(hdc,xx, yy,NULL);
1027 LineTo( hdc,pdp->sw, yy);
1028 rct.right =
1029 rct.left = xx;
1030 rct.top =
1031 rct.bottom = yy;
1032 DrawText(hdc, lab, -1, &rct, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOCLIP);
1033 }
1034
1035 void
loose_label(HDC hdc,plot_info * pdp,double min,double max,void (* pfunc)(HDC hdc,plot_info * pdp,double,char *))1036 loose_label(HDC hdc, plot_info *pdp, double min, double max, void (*pfunc)(HDC hdc, plot_info *pdp, double, char *)
1037 ) {
1038 char str[6], temp[20];
1039 int nfrac;
1040 double d;
1041 double graphmin, graphmax;
1042 double range,x;
1043
1044 range = nicenum(min-max,0);
1045 d = nicenum(range/(NTICK-1),1);
1046 graphmin = floor(min/d) * d;
1047 graphmax = ceil(max/d) * d;
1048 nfrac = (int)MAX(-floor(log10(d)),0);
1049 sprintf(str,"%%.%df", nfrac);
1050 for (x = graphmin; x < graphmax + 0.5 * d; x += d) {
1051 sprintf(temp,str,x);
1052 pfunc(hdc,pdp,x,temp);
1053 }
1054 }
1055
1056 void
DoPlot(HDC hdc,plot_info * p)1057 DoPlot(
1058 HDC hdc,
1059 plot_info *p
1060 ) {
1061 int i, j;
1062 int lx,ly; /* Last x,y */
1063 HPEN pen;
1064
1065 pen = CreatePen(PS_DOT,0,RGB(200,200,200));
1066
1067 SaveDC(hdc);
1068 SelectObject(hdc,pen);
1069
1070 /* Plot horizontal axis */
1071 if (p->revx)
1072 loose_label(hdc, p, p->mxx, p->mnx, xtick);
1073 else
1074 loose_label(hdc, p, p->mnx, p->mxx, xtick);
1075
1076 /* Plot vertical axis */
1077 loose_label(hdc, p, p->mny, p->mxy, ytick);
1078
1079 RestoreDC(hdc,-1);
1080 DeleteObject(pen);
1081
1082 if (p->graph) { /* Up to MXGPHS graphs + crosses */
1083 int gcolors[MXGPHS][3] = {
1084 { 0, 0, 0}, /* Black */
1085 { 210, 30, 0}, /* Red */
1086 { 0, 200, 90}, /* Green */
1087 { 0, 10, 255}, /* Blue */
1088 { 200, 200, 0}, /* Yellow */
1089 { 220, 0, 255}, /* Purple */
1090 { 136, 86, 68}, /* Brown */
1091 { 248, 95, 0}, /* Orange */
1092 { 160, 160, 160}, /* Grey */
1093 { 220, 220, 220} /* White */
1094 };
1095 for (j = MXGPHS-1; j >= 0; j--) {
1096 double *yp = p->yy[j];
1097
1098 if (yp == NULL)
1099 continue;
1100
1101 pen = CreatePen(PS_SOLID,ILTHICK,RGB(gcolors[j][0],gcolors[j][1],gcolors[j][2]));
1102 SelectObject(hdc,pen);
1103
1104 lx = (int)((p->x1[0] - p->mnx) * p->scx + 0.5);
1105 ly = (int)(( yp[0] - p->mny) * p->scy + 0.5);
1106
1107 for (i = 0; i < p->n; i++) {
1108 int cx,cy;
1109 cx = (int)((p->x1[i] - p->mnx) * p->scx + 0.5);
1110 cy = (int)(( yp[i] - p->mny) * p->scy + 0.5);
1111
1112 MoveToEx(hdc, 10 + lx, p->sh - 10 - ly, NULL);
1113 LineTo(hdc, 10 + cx, p->sh - 10 - cy);
1114 if (p->flags & PLOTF_GRAPHCROSSES) {
1115 MoveToEx(hdc, 10 + cx - 5, p->sh - 10 - cy - 5, NULL);
1116 LineTo(hdc, 10 + cx + 5, p->sh - 10 - cy + 5);
1117 LineTo(hdc, 10 + cx - 5, p->sh - 10 - cy + 5);
1118 }
1119 lx = cx;
1120 ly = cy;
1121 }
1122 DeleteObject(pen);
1123 }
1124
1125 } else { /* Vectors with cross */
1126
1127 pen = CreatePen(PS_SOLID,ILTHICK,RGB(0,0,0));
1128 SelectObject(hdc,pen);
1129
1130 if (p->ntext != NULL) {
1131 HFONT fon;
1132
1133 fon = CreateFont(12, 0, 0, 0, FW_LIGHT, FALSE, FALSE, FALSE, ANSI_CHARSET,
1134 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
1135 FF_DONTCARE, NULL);
1136
1137 if (fon == NULL)
1138 fprintf(stderr,"plot: CreateFont returned NULL\n");
1139 else {
1140 SelectObject(hdc,fon);
1141 DeleteObject(fon);
1142 }
1143 }
1144
1145 for (i = 0; i < p->n; i++) {
1146 int cx,cy;
1147
1148 lx = (int)((p->x1[i] - p->mnx) * p->scx + 0.5);
1149 ly = (int)((p->yy[0][i] - p->mny) * p->scy + 0.5);
1150
1151 cx = (int)((p->x2[i] - p->mnx) * p->scx + 0.5);
1152 cy = (int)((p->yy[1][i] - p->mny) * p->scy + 0.5);
1153
1154 MoveToEx(hdc, 10 + lx, p->sh - 10 - ly, NULL);
1155 LineTo(hdc, 10 + cx, p->sh - 10 - cy);
1156
1157 if (p->flags & PLOTF_VECCROSSES) {
1158 MoveToEx(hdc, 10 + cx - 5, p->sh - 10 - cy - 5, NULL);
1159 LineTo(hdc, 10 + cx + 5, p->sh - 10 - cy + 5);
1160 MoveToEx(hdc, 10 + cx + 5, p->sh - 10 - cy - 5, NULL);
1161 LineTo(hdc, 10 + cx - 5, p->sh - 10 - cy + 5);
1162 }
1163
1164 if (p->ntext != NULL) {
1165 RECT rct;
1166 rct.right =
1167 rct.left = 10 + cx + 10;
1168 rct.top =
1169 rct.bottom = p->sh - 10 - cy + 10;
1170 DrawText(hdc, p->ntext[i], -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
1171 }
1172 }
1173 DeleteObject(pen);
1174 }
1175
1176 /* Extra points */
1177 if (p->x7 != NULL && p->y7 != NULL && p->m > 0 ) {
1178 pen = CreatePen(PS_SOLID,ILTHICK,RGB(210,150,0));
1179 SelectObject(hdc,pen);
1180
1181 if (p->mtext != NULL) {
1182 HFONT fon;
1183
1184
1185 fon = CreateFont(12, 0, 0, 0, FW_LIGHT, FALSE, FALSE, FALSE, ANSI_CHARSET,
1186 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
1187 FF_DONTCARE, NULL);
1188
1189 if (fon == NULL)
1190 fprintf(stderr,"plot: CreateFont returned NULL\n");
1191 else {
1192 SelectObject(hdc,fon);
1193 DeleteObject(fon);
1194 }
1195 }
1196
1197 for (i = 0; i < p->m; i++) {
1198 lx = (int)((p->x7[i] - p->mnx) * p->scx + 0.5);
1199 ly = (int)((p->y7[i] - p->mny) * p->scy + 0.5);
1200
1201 if (p->mcols != NULL) {
1202 int rgb[3];
1203
1204 for (j = 0; j < 3; j++)
1205 rgb[j] = (int)(p->mcols[i].rgb[j] * 255.0 + 0.5);
1206
1207 DeleteObject(pen);
1208 pen = CreatePen(PS_SOLID,ILTHICK,RGB(rgb[0],rgb[1],rgb[2]));
1209 SelectObject(hdc,pen);
1210
1211 if (p->mtext != NULL)
1212 SetTextColor(hdc, RGB(rgb[0],rgb[1],rgb[2]));
1213 }
1214 MoveToEx(hdc, 10 + lx - 5, p->sh - 10 - ly, NULL);
1215 LineTo(hdc, 10 + lx + 5, p->sh - 10 - ly);
1216 MoveToEx(hdc, 10 + lx, p->sh - 10 - ly - 5, NULL);
1217 LineTo(hdc, 10 + lx, p->sh - 10 - ly + 5);
1218
1219 if (p->mtext != NULL) {
1220 RECT rct;
1221 rct.right =
1222 rct.left = 10 + lx + 10;
1223 rct.top =
1224 rct.bottom = p->sh - 10 - ly - 10;
1225 DrawText(hdc, p->mtext[i], -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
1226 }
1227 }
1228 DeleteObject(pen);
1229 }
1230 /* Extra vectors */
1231 if (p->x8 != NULL && p->y8 != NULL && p->x9 != NULL && p->y9 && p->o > 0 ) {
1232 pen = CreatePen(PS_SOLID,ILTHICK,RGB(150,255,255));
1233 SelectObject(hdc,pen);
1234
1235 for (i = 0; i < p->o; i++) {
1236 int cx,cy;
1237
1238 lx = (int)((p->x8[i] - p->mnx) * p->scx + 0.5);
1239 ly = (int)((p->y8[i] - p->mny) * p->scy + 0.5);
1240
1241 cx = (int)((p->x9[i] - p->mnx) * p->scx + 0.5);
1242 cy = (int)((p->y9[i] - p->mny) * p->scy + 0.5);
1243
1244 if (p->ocols != NULL) {
1245 int rgb[3];
1246
1247 for (j = 0; j < 3; j++)
1248 rgb[j] = (int)(p->ocols[i].rgb[j] * 255.0 + 0.5);
1249
1250 DeleteObject(pen);
1251 pen = CreatePen(PS_SOLID,ILTHICK,RGB(rgb[0],rgb[1],rgb[2]));
1252 SelectObject(hdc,pen);
1253
1254 if (p->mtext != NULL)
1255 SetTextColor(hdc, RGB(rgb[0],rgb[1],rgb[2]));
1256 }
1257 MoveToEx(hdc, 10 + lx, p->sh - 10 - ly, NULL);
1258 LineTo(hdc, 10 + cx, p->sh - 10 - cy);
1259 }
1260 DeleteObject(pen);
1261 }
1262
1263 // while(!kbhit());
1264 }
1265
1266 #else /* !NT */
1267
1268 /* ************************** APPLE OSX Cocoa version ****************** */
1269 #ifdef __APPLE__
1270
1271 #include <Foundation/Foundation.h>
1272 #include <AppKit/AppKit.h>
1273
1274 #ifndef CGFLOAT_DEFINED
1275 #ifdef __LP64__
1276 typedef double CGFloat;
1277 #else
1278 typedef float CGFloat;
1279 #endif /* defined(__LP64__) */
1280 #endif
1281
1282 #ifdef DODEBUG
1283 # define debugf(xx) printf xx
1284 #else
1285 # define debugf(xx)
1286 #endif
1287
1288 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1289
1290
1291 @class PLWin;
1292 @class PLView;
1293
1294 /* Our static instance variables */
1295 typedef struct {
1296 PLWin *window; /* NSWindow */
1297 PLView *view; /* NSTextField */
1298 volatile int plot_signal; /* Signal a key or quit */
1299 } cntx_t;
1300
1301 /* Global plot instanc */
1302
1303 cntx_t *plot_cx = NULL;
1304
1305 // - - - - - - - - - - - - - - - - - - - - - - - - -
1306 @interface PLView : NSView {
1307 cntx_t *cntx;
1308 }
1309 - (void)setCntx:(cntx_t *)cntx;
1310 @end
1311
1312 @implementation PLView
1313
1314 - (void)setCntx:(cntx_t *)val {
1315 cntx = val;
1316 }
1317
1318 /* This function does the work */
1319 static void DoPlot(NSRect *rect, plot_info *pdp);
1320
1321 - (void)drawRect:(NSRect)rect {
1322
1323 /* Use global plot data struct for now */
1324 DoPlot(&rect, &pd);
1325 }
1326
1327 @end
1328
1329 /* Function called back by main thread to trigger a drawRect */
1330
doSetNeedsDisplay(void * cntx)1331 static void doSetNeedsDisplay(void *cntx) {
1332 cntx_t *cx = (cntx_t *)cntx;
1333
1334 [cx->view setNeedsDisplay: YES ];
1335 }
1336
1337 // - - - - - - - - - - - - - - - - - - - - - - - - -
1338
1339 @interface PLWin : NSWindow {
1340 cntx_t *cntx;
1341 }
1342 - (void)setCntx:(cntx_t *)cntx;
1343 @end
1344
1345 @implementation PLWin
1346
1347 - (void)setCntx:(cntx_t *)val {
1348 cntx = val;
1349 }
1350
1351 - (BOOL)canBecomeMainWindow {
1352 return YES;
1353 }
1354
1355 - (void)keyDown:(NSEvent *)event {
1356 const char *chars;
1357
1358 chars = [[event characters] UTF8String];
1359 // printf("Got Window KeyDown type %d char %s\n",(int)[event type], chars);
1360
1361 if (chars[0] == ' '
1362 || chars[0] == '\r') {
1363 // printf("Set plot_signal = 1\n");
1364 plot_cx->plot_signal = 1;
1365 }
1366 }
1367
1368 - (BOOL)windowShouldClose:(id)sender {
1369 // printf("Got Window windowShouldClose\n");
1370
1371 [NSApp terminate: nil];
1372 return YES;
1373 }
1374
1375 @end
1376
1377 /* Create our window */
create_my_win(void * cntx)1378 static void create_my_win(void *cntx) {
1379 cntx_t *cx = (cntx_t *)cntx;
1380 NSRect wRect;
1381
1382 /* Create Window */
1383 wRect.origin.x = 100;
1384 wRect.origin.y = 100;
1385 wRect.size.width = (int)(DEFWWIDTH*pd.ratio+0.5);
1386 wRect.size.height = DEFWHEIGHT;
1387
1388 cx->window = [[PLWin alloc] initWithContentRect: wRect
1389 styleMask: (NSTitledWindowMask |
1390 NSClosableWindowMask |
1391 NSMiniaturizableWindowMask |
1392 NSResizableWindowMask)
1393 backing: NSBackingStoreBuffered
1394 defer: YES
1395 screen: nil]; /* Main screen */
1396
1397 [cx->window setBackgroundColor: [NSColor whiteColor]];
1398
1399 [cx->window setLevel: NSMainMenuWindowLevel]; // ~~99
1400
1401 [cx->window setTitle: @"PlotWin"];
1402
1403 /* Use our view for the whole window to draw plot */
1404 cx->view = [PLView new];
1405 [cx->view setCntx:(void *)cx];
1406 [cx->window setContentView: cx->view];
1407
1408 [cx->window makeKeyAndOrderFront: nil];
1409
1410 // [cx->window makeMainWindow];
1411 }
1412
1413 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1414
1415 /*
1416 Cocoa NSApp is pretty horrible - it will only get user events
1417 if created and run in the main thread. So the only way we can
1418 decouble the windows from the application is to intercept
1419 main() and create a secondary thread to run the appication while
1420 leaving main() in reserve for creating an NSApp and windows.
1421 */
1422
1423 /* Superset implementation function: */
1424 /* return 0 on success, -1 on error */
1425 /* Hybrid Graph uses x1 : y1, y2, y3, y4, y5, y6 for up to 6 graph curves + */
1426 /* optional diagonal crosses at x7, y7 in yellow (x2 == NULL). */
1427 /* Vector uses x1, y1 to x2, y2 as a vector with a (optional) diagonal cross at x2, y2 */
1428 /* all in black with annotation ntext at the cross, */
1429 /* plus a (optiona) diagonal cross at x7, y7 in yellow. The color for x7, y7 can be */
1430 /* overidden by an array of colors mcols, plus optional label text mtext. (x2 != NULL) */
1431 /* n = number of points/vectors. -ve for reversed X axis */
1432 /* m = number of extra points (x2,y3 or x7,y7) */
1433 /* x8,y8 to x9,y9 are extra optional vectors with optional colors */
do_plot_imp(int flags,double xmin,double xmax,double ymin,double ymax,double ratio,int dowait,double * x1,double * x2,double * yy[MXGPHS],char ** ntext,int n,double * x7,double * y7,plot_col * mcols,char ** mtext,int m,double * x8,double * y8,double * x9,double * y9,plot_col * ocols,int o)1434 static int do_plot_imp(
1435 int flags,
1436 double xmin, double xmax, double ymin, double ymax, /* Bounding box */
1437 double ratio, /* Aspect ratio of window, X/Y */
1438 int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
1439 double *x1, double *x2,
1440 double *yy[MXGPHS], char **ntext,
1441 int n,
1442 double *x7, double *y7, plot_col *mcols, char **mtext,
1443 int m,
1444 double *x8, double *y8, double *x9, double*y9, plot_col *ocols,
1445 int o
1446 ) {
1447 /* Put information in global pd */
1448 {
1449 int j;
1450 double xr,yr;
1451
1452 pd.flags = flags;
1453 pd.dowait = dowait;
1454 pd.ratio = ratio;
1455
1456 pd.mnx = xmin;
1457 pd.mny = ymin;
1458 pd.mxx = xmax;
1459 pd.mxy = ymax;
1460
1461 /* Allow some extra arround plot */
1462 xr = pd.mxx - pd.mnx;
1463 yr = pd.mxy - pd.mny;
1464 if (xr < 1e-6)
1465 xr = 1e-6;
1466 if (yr < 1e-6)
1467 yr = 1e-6;
1468 pd.mnx -= xr/10.0;
1469 pd.mxx += xr/10.0;
1470 pd.mny -= yr/10.0;
1471 pd.mxy += yr/10.0;
1472
1473 /* Transfer raw point info */
1474 if (x2 == NULL)
1475 pd.graph = 1; /* 6 graphs + points */
1476 else
1477 pd.graph = 0;
1478 pd.x1 = x1;
1479 pd.x2 = x2;
1480 for (j = 0; j < MXGPHS; j++)
1481 pd.yy[j] = yy[j];
1482 pd.ntext = ntext;
1483 pd.n = abs(n);
1484
1485 if (n < 0) {
1486 double tt;
1487 tt = pd.mxx;
1488 pd.mxx = pd.mnx;
1489 pd.mnx = tt;
1490 pd.revx = 1;
1491 } else {
1492 pd.revx = 0;
1493 }
1494 pd.x7 = x7;
1495 pd.y7 = y7;
1496 pd.mcols = mcols;
1497 pd.mtext = mtext;
1498 pd.m = abs(m);
1499
1500 pd.x8 = x8;
1501 pd.y8 = y8;
1502 pd.x9 = x9;
1503 pd.y9 = y9;
1504 pd.ocols = ocols;
1505 pd.o = abs(o);
1506 }
1507
1508 ui_UsingGUI();
1509
1510 /* If we may be in a different thread to the main thread or */
1511 /* the application thread, establish our own pool. */
1512 NSAutoreleasePool *tpool = nil;
1513 if (pthread_self() != ui_thid
1514 && pthread_self() != ui_main_thid)
1515 tpool = [NSAutoreleasePool new];
1516
1517 /* If needed, create the indow */
1518 if (plot_cx == NULL) {
1519
1520 /* If there is no NSApp, then we haven't run main() in libui before */
1521 /* main() in the application. */
1522 if (NSApp == nil) {
1523 fprintf(stderr,"NSApp is nil - need to rename main() to main() and link with libui !\n");
1524 exit(1);
1525 }
1526
1527 if ((plot_cx = (cntx_t *)calloc(sizeof(cntx_t), 1)) == NULL)
1528 error("new_dispwin: Malloc failed (cntx_t)\n");
1529
1530 /* Prepare to wait for events */
1531 ui_aboutToWait();
1532
1533 /* Run the window creation in the main thread and wait for it */
1534 ui_runInMainThreadAndWait((void *)plot_cx, create_my_win);
1535
1536 /* Wait for events generated by window creation to complete */
1537 ui_waitForEvents();
1538
1539 } else { /* Trigger an update */
1540 // [plot_cx->view setNeedsDisplay: YES ];
1541
1542 /* Prepare to wait for events */
1543 ui_aboutToWait();
1544
1545 /* Run the window creation in the main thread and wait for it */
1546 ui_runInMainThreadAndWait((void *)plot_cx, doSetNeedsDisplay);
1547
1548 /* Wait for any events generated by paint to complete */
1549 ui_waitForEvents();
1550 }
1551
1552 /* (Main thread will service events) */
1553
1554 /* Wait until for a key if we should */
1555 if (dowait > 0) { /* Wait for a space key */
1556 for (plot_cx->plot_signal = 0; plot_cx->plot_signal == 0;) {
1557 struct timespec ts;
1558
1559 ts.tv_sec = 100 / 1000;
1560 ts.tv_nsec = (100 % 1000) * 1000000;
1561 nanosleep(&ts, NULL);
1562 }
1563 } else if (dowait < 0) {
1564 struct timespec ts;
1565 int msec = -dowait * 1000;
1566
1567 ts.tv_sec = msec / 1000;
1568 ts.tv_nsec = (msec % 1000) * 1000000;
1569 nanosleep(&ts, NULL);
1570 }
1571
1572 if (tpool != nil)
1573 [tpool release];
1574
1575 return 0;
1576 }
1577
1578 /* - - - - - - - - - - - - - - - - - - - - - - - - - */
1579 /* Cleanup code (not called) */
1580
cleanup()1581 static void cleanup() {
1582 [plot_cx->window release]; /* Take down the plot window */
1583 free(plot_cx);
1584 plot_cx = NULL;
1585 }
1586
1587 /* - - - - - - - - - - - - - - - - - - - - - - - - - - */
1588
1589 /* Utility to draw text in Cocoa with centering */
1590 /* Size is points */
1591 /* Flags 0x1 == horizontal center */
1592 /* Flags 0x2 == vertical center */
ADrawText(NSColor * col,float size,float x,float y,int flags,char * text)1593 static void ADrawText(NSColor *col, float size, float x, float y, int flags, char *text) {
1594 NSFont* font = [NSFont systemFontOfSize:size];
1595 NSDictionary *att = [NSDictionary dictionaryWithObjectsAndKeys:
1596 font, NSFontAttributeName,
1597 col, NSForegroundColorAttributeName,
1598 nil];
1599 NSString *str = [[NSString alloc] initWithUTF8String: text];
1600
1601 if (flags != 0x0) {
1602 NSSize size;
1603
1604 /* Figure out how big it will be */
1605 size = [str sizeWithAttributes: att ];
1606 if (flags & 0x1) {
1607 double w = fabs(size.width);
1608 x -= 0.5 * w;
1609 }
1610 if (flags & 0x2) {
1611 double h = fabs(size.height);
1612 y -= 0.5 * h;
1613 }
1614 }
1615
1616 [str drawAtPoint: NSMakePoint(x, y) withAttributes: att];
1617 [str release]; /* Others are autorelease */
1618 }
1619
1620 /* Draw a line */
1621 /* We re-use the same path so that we can set the dash style */
ADrawLine(NSBezierPath * path,float xs,float ys,float xe,float ye)1622 static void ADrawLine(NSBezierPath *path, float xs, float ys, float xe, float ye) {
1623 [path removeAllPoints ];
1624 [path moveToPoint:NSMakePoint(xs, ys)];
1625 [path lineToPoint:NSMakePoint(xe, ye)];
1626 [path stroke];
1627 }
1628
1629 /* Draw X axis grid lines */
1630 void
xtick(plot_info * pdp,NSBezierPath * path,NSColor * lcol,NSColor * tcol,double x,char * lab)1631 xtick(
1632 plot_info *pdp,
1633 NSBezierPath *path,
1634 NSColor *lcol,
1635 NSColor *tcol,
1636 double x, char *lab
1637 ) {
1638 float xx, yy;
1639
1640 xx = 20.0 + (x - pdp->mnx) * pdp->scx;
1641 yy = 20.0;
1642
1643 [lcol setStroke]; /* There is a bug in 10.4 which resets this after each stroke */
1644 ADrawLine(path, xx, yy, xx, (float)pdp->sh);
1645 ADrawText(tcol, 10.0, xx, 5.0, 0x1, lab);
1646 }
1647
1648 /* Draw Y axis grid lines */
1649 void
ytick(plot_info * pdp,NSBezierPath * path,NSColor * lcol,NSColor * tcol,double y,char * lab)1650 ytick(
1651 plot_info *pdp,
1652 NSBezierPath *path,
1653 NSColor *lcol,
1654 NSColor *tcol,
1655 double y, char *lab
1656 ) {
1657 float xx, yy;
1658
1659 xx = 20.0;
1660 yy = 20.0 + (y - pdp->mny) * pdp->scy;
1661
1662 [lcol setStroke]; /* There is a bug in 10.4 which resets this after each stroke */
1663 ADrawLine(path, xx, yy, (float)pdp->sw, yy);
1664 ADrawText(tcol, 10.0, 3.0, yy, 0x2, lab);
1665 }
1666
1667 void
loose_label(plot_info * pdp,NSBezierPath * path,NSColor * lcol,NSColor * tcol,double min,double max,void (* pfunc)(plot_info * pdp,NSBezierPath * path,NSColor * lcol,NSColor * tcol,double,char *))1668 loose_label(
1669 plot_info *pdp,
1670 NSBezierPath *path,
1671 NSColor *lcol,
1672 NSColor *tcol,
1673 double min, double max,
1674 void (*pfunc)(plot_info *pdp, NSBezierPath *path, NSColor *lcol, NSColor *tcol, double, char *)
1675 ) {
1676 char str[6], temp[20];
1677 int nfrac;
1678 double d;
1679 double graphmin, graphmax;
1680 double range,x;
1681
1682 range = nicenum(min-max,0);
1683 d = nicenum(range/(NTICK-1),1);
1684 graphmin = floor(min/d) * d;
1685 graphmax = ceil(max/d) * d;
1686 nfrac = (int)MAX(-floor(log10(d)),0);
1687 sprintf(str,"%%.%df", nfrac);
1688 for (x = graphmin; x < graphmax + 0.5 * d; x += d) {
1689 sprintf(temp,str,x);
1690 pfunc(pdp, path, lcol, tcol, x, temp);
1691 }
1692 }
1693
1694 /* Called from within view to plot overall graph */
DoPlot(NSRect * rect,plot_info * pdp)1695 static void DoPlot(NSRect *rect, plot_info *pdp) {
1696 int i, j;
1697 int lx,ly; /* Last x,y */
1698 CGFloat dash_list[2] = {7.0, 2.0};
1699 /* Note path and tcol are autorelease */
1700 NSBezierPath *path = [NSBezierPath bezierPath]; /* Path to use */
1701 NSColor *lcol = nil;
1702 NSColor *tcol = nil;
1703
1704 /* Setup the plot info structure for this drawing */
1705 /* Note port rect is raster like, pdp/Quartz2D is Postscript like */
1706 pdp->sx = rect->origin.x;
1707 pdp->sy = rect->origin.y;
1708 pdp->sw = rect->size.width;
1709 pdp->sh = rect->size.height;
1710 pdp->scx = (pdp->sw - 20)/(pdp->mxx - pdp->mnx);
1711 pdp->scy = (pdp->sh - 20)/(pdp->mxy - pdp->mny);
1712
1713 /* Plot the axis lines */
1714 [path setLineWidth:1.0];
1715 [path setLineDash: dash_list count: 2 phase: 0.0 ]; /* Set dashed lines for axes */
1716
1717 /* Make sure text is black */
1718 tcol = [NSColor colorWithCalibratedRed: 0.0
1719 green: 0.0
1720 blue: 0.0
1721 alpha: 1.0];
1722
1723 lcol = [NSColor colorWithCalibratedRed:0.7 green: 0.7 blue:0.7 alpha: 1.0]; /* Grey */
1724
1725 /* Plot horizontal axis */
1726 if (pdp->revx)
1727 loose_label(pdp, path, lcol, tcol, pdp->mxx, pdp->mnx, xtick);
1728 else
1729 loose_label(pdp, path, lcol, tcol, pdp->mnx, pdp->mxx, xtick);
1730
1731 /* Plot vertical axis */
1732 loose_label(pdp, path, lcol, tcol, pdp->mny, pdp->mxy, ytick);
1733
1734 /* Set to non-dashed line */
1735 [path setLineWidth: LTHICK];
1736 [path setLineDash: NULL count: 0 phase: 0.0 ];
1737
1738 if (pdp->graph) { /* Up to 6 graphs */
1739 int gcolors[MXGPHS][3] = {
1740 { 0, 0, 0}, /* Black */
1741 { 210, 30, 0}, /* Red */
1742 { 0, 200, 90}, /* Green */
1743 { 0, 10, 255}, /* Blue */
1744 { 200, 200, 0}, /* Yellow */
1745 { 220, 0, 255}, /* Purple */
1746 { 136, 86, 68}, /* Brown */
1747 { 248, 95, 0}, /* Orange */
1748 { 160, 160, 160}, /* Grey */
1749 { 220, 220, 220} /* White */
1750 };
1751 for (j = MXGPHS-1; j >= 0; j--) {
1752 double *yp = pdp->yy[j];
1753
1754 if (yp == NULL)
1755 continue;
1756 [[NSColor colorWithCalibratedRed: gcolors[j][0]/255.0
1757 green: gcolors[j][1]/255.0
1758 blue: gcolors[j][2]/255.0
1759 alpha: 1.0] setStroke];
1760
1761 if (pdp->n > 0) {
1762 lx = (int)((pdp->x1[0] - pdp->mnx) * pdp->scx + 0.5);
1763 ly = (int)(( yp[0] - pdp->mny) * pdp->scy + 0.5);
1764 }
1765
1766 for (i = 1; i < pdp->n; i++) {
1767 int cx,cy;
1768 cx = (int)((pdp->x1[i] - pdp->mnx) * pdp->scx + 0.5);
1769 cy = (int)(( yp[i] - pdp->mny) * pdp->scy + 0.5);
1770
1771 ADrawLine(path, 20.0 + lx, 20.0 + ly, 20 + cx, 20.0 + cy);
1772 if (pdp->flags & PLOTF_GRAPHCROSSES) {
1773 ADrawLine(path, 20.0 + cx - 5, 20.0 - cy - 5, 20.0 + cx + 5, 20.0 + cy + 5);
1774 ADrawLine(path, 20.0 + cx + 5, 20.0 - cy - 5, 20.0 + cx - 5, 20.0 + cy + 5);
1775 }
1776 lx = cx;
1777 ly = cy;
1778 }
1779 }
1780
1781 } else { /* Vectors */
1782 [[NSColor colorWithCalibratedRed: 0.0
1783 green: 0.0
1784 blue: 0.0
1785 alpha: 1.0] setStroke];
1786 if (pdp->ntext != NULL) {
1787 tcol = [NSColor colorWithCalibratedRed: 0.0
1788 green: 0.0
1789 blue: 0.0
1790 alpha: 1.0];
1791 }
1792 for (i = 0; i < pdp->n; i++) {
1793 int cx,cy;
1794
1795 lx = (int)((pdp->x1[i] - pdp->mnx) * pdp->scx + 0.5);
1796 ly = (int)((pdp->yy[0][i] - pdp->mny) * pdp->scy + 0.5);
1797
1798 cx = (int)((pdp->x2[i] - pdp->mnx) * pdp->scx + 0.5);
1799 cy = (int)((pdp->yy[1][i] - pdp->mny) * pdp->scy + 0.5);
1800
1801 ADrawLine(path, 20.0 + lx, 20.0 + ly, 20.0 + cx, 20.0 + cy);
1802
1803 if (pdp->flags & PLOTF_VECCROSSES) {
1804 ADrawLine(path, 20.0 + cx - 5, 20.0 + cy - 5, 20.0 + cx + 5, 20.0 + cy + 5);
1805 ADrawLine(path, 20.0 + cx + 5, 20.0 + cy - 5, 20.0 + cx - 5, 20.0 + cy + 5);
1806 }
1807
1808 if (pdp->ntext != NULL)
1809 ADrawText(tcol, 9.0, 20.0 + cx + 9, 20.0 + cy - 7, 0x1, pdp->ntext[i]);
1810 }
1811 }
1812
1813 /* Extra points */
1814 if (pdp->x7 != NULL && pdp->y7 != NULL && pdp->m > 0 ) {
1815 [[NSColor colorWithCalibratedRed: 0.82 /* Orange ? */
1816 green: 0.59
1817 blue: 0.0
1818 alpha: 1.0] setStroke];
1819
1820 for (i = 0; i < pdp->m; i++) {
1821
1822 if (pdp->mcols != NULL) {
1823 [[NSColor colorWithCalibratedRed: pdp->mcols[i].rgb[0]
1824 green: pdp->mcols[i].rgb[1]
1825 blue: pdp->mcols[i].rgb[2]
1826 alpha: 1.0] setStroke];
1827
1828 if (pdp->mtext != NULL) {
1829 tcol = [NSColor colorWithCalibratedRed: pdp->mcols[i].rgb[0]
1830 green: pdp->mcols[i].rgb[1]
1831 blue: pdp->mcols[i].rgb[2]
1832 alpha: 1.0];
1833 }
1834 }
1835 lx = (int)((pdp->x7[i] - pdp->mnx) * pdp->scx + 0.5);
1836 ly = (int)((pdp->y7[i] - pdp->mny) * pdp->scy + 0.5);
1837
1838 ADrawLine(path, 20.0 + lx - 5, 20.0 + ly, 20.0 + lx + 5, 20.0 + ly);
1839 ADrawLine(path, 20.0 + lx, 20.0 + ly - 5, 20.0 + lx, 20.0 + ly + 5);
1840
1841 if (pdp->mtext != NULL) {
1842 ADrawText(tcol, 9.0, 20.0 + lx + 9, 20.0 + ly + 7, 0x1, pdp->mtext[i]);
1843 }
1844 }
1845 }
1846
1847 /* Extra vectors */
1848 if (pdp->x8 != NULL && pdp->y8 != NULL && pdp->x9 != NULL && pdp->y9 && pdp->o > 0 ) {
1849 [[NSColor colorWithCalibratedRed: 0.5 /* Light blue */
1850 green: 0.9
1851 blue: 0.9
1852 alpha: 1.0] setStroke];
1853
1854 for (i = 0; i < pdp->o; i++) {
1855 int cx,cy;
1856
1857 if (pdp->ocols != NULL) {
1858 [[NSColor colorWithCalibratedRed: pdp->ocols[i].rgb[0]
1859 green: pdp->ocols[i].rgb[1]
1860 blue: pdp->ocols[i].rgb[2]
1861 alpha: 1.0] setStroke];
1862 if (pdp->mtext != NULL) {
1863 tcol = [NSColor colorWithCalibratedRed: pdp->ocols[i].rgb[0]
1864 green: pdp->ocols[i].rgb[1]
1865 blue: pdp->ocols[i].rgb[2]
1866 alpha: 1.0];
1867 }
1868 }
1869 lx = (int)((pdp->x8[i] - pdp->mnx) * pdp->scx + 0.5);
1870 ly = (int)((pdp->y8[i] - pdp->mny) * pdp->scy + 0.5);
1871
1872 cx = (int)((pdp->x9[i] - pdp->mnx) * pdp->scx + 0.5);
1873 cy = (int)((pdp->y9[i] - pdp->mny) * pdp->scy + 0.5);
1874
1875 ADrawLine(path, 20.0 + lx, 20.0 + ly, 20.0 + cx, 20.0 + cy);
1876 }
1877 }
1878 }
1879
1880 #else /* Assume UNIX + X11 */
1881 /* ********************************** X11 version ********************** */
1882
1883 /* !!!! There is a problem if the user closes the window - an X11 error results */
1884 /* This seems to happen before a DestroyNotify !. How to fix ??? !!!! */
1885
1886 #include <X11/Xlib.h>
1887 #include <X11/Xutil.h>
1888
1889 #ifdef DODEBUG
1890 # define debugf(xx) printf xx
1891 #else
1892 # define debugf(xx)
1893 #endif
1894
1895 void DoPlot(Display *mydisplay, Window mywindow, GC mygc, plot_info *pdp);
1896
1897 /* Superset implementation function: */
1898 /* return 0 on success, -1 on error */
1899 /* Hybrid Graph uses x1 : y1, y2, y3, y4, y5, y6 for up to 6 graph curves + */
1900 /* optional diagonal crosses at x7, y7 in yellow (x2 == NULL). */
1901 /* Vector uses x1, y1 to x2, y2 as a vector with a (optional) diagonal cross at x2, y2 */
1902 /* all in black with annotation ntext at the cross, */
1903 /* plus a (optiona) diagonal cross at x7, y7 in yellow. The color for x7, y7 can be */
1904 /* overidden by an array of colors mcols, plus optional label text mtext. (x2 != NULL) */
1905 /* n = number of points/vectors. -ve for reversed X axis */
1906 /* m = number of extra points (x2,y3 or x7,y7) */
1907 /* x8,y8 to x9,y9 are extra optional vectors with optional colors */
do_plot_imp(int flags,double xmin,double xmax,double ymin,double ymax,double ratio,int dowait,double * x1,double * x2,double * yy[MXGPHS],char ** ntext,int n,double * x7,double * y7,plot_col * mcols,char ** mtext,int m,double * x8,double * y8,double * x9,double * y9,plot_col * ocols,int o)1908 static int do_plot_imp(
1909 int flags,
1910 double xmin, double xmax, double ymin, double ymax, /* Bounding box */
1911 double ratio, /* Aspect ratio of window, X/Y */
1912 int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
1913 double *x1, double *x2,
1914 double *yy[MXGPHS], char **ntext,
1915 int n,
1916 double *x7, double *y7, plot_col *mcols, char **mtext,
1917 int m,
1918 double *x8, double *y8, double *x9, double*y9, plot_col *ocols,
1919 int o
1920 ) {
1921 {
1922 int j;
1923 double xr,yr;
1924
1925 pd.flags = flags;
1926 pd.dowait = dowait;
1927 pd.ratio = ratio;
1928
1929 pd.mnx = xmin;
1930 pd.mny = ymin;
1931 pd.mxx = xmax;
1932 pd.mxy = ymax;
1933
1934 /* Allow some extra arround plot */
1935 xr = pd.mxx - pd.mnx;
1936 yr = pd.mxy - pd.mny;
1937 if (xr < 1e-6)
1938 xr = 1e-6;
1939 if (yr < 1e-6)
1940 yr = 1e-6;
1941 pd.mnx -= xr/10.0;
1942 pd.mxx += xr/10.0;
1943 pd.mny -= yr/10.0;
1944 pd.mxy += yr/10.0;
1945
1946 /* Transfer raw point info */
1947 if (x2 == NULL)
1948 pd.graph = 1; /* 6 graphs + points */
1949 else
1950 pd.graph = 0;
1951 pd.x1 = x1;
1952 pd.x2 = x2;
1953 for (j = 0; j < MXGPHS; j++)
1954 pd.yy[j] = yy[j];
1955 pd.ntext = ntext;
1956 pd.n = abs(n);
1957
1958 if (n < 0) {
1959 double tt;
1960 tt = pd.mxx;
1961 pd.mxx = pd.mnx;
1962 pd.mnx = tt;
1963 pd.revx = 1;
1964 } else {
1965 pd.revx = 0;
1966 }
1967 pd.x7 = x7;
1968 pd.y7 = y7;
1969 pd.mcols = mcols;
1970 pd.mtext = mtext;
1971 pd.m = abs(m);
1972
1973 pd.x8 = x8;
1974 pd.y8 = y8;
1975 pd.x9 = x9;
1976 pd.y9 = y9;
1977 pd.ocols = ocols;
1978 pd.o = abs(o);
1979 }
1980
1981 {
1982 /* stuff for X windows */
1983 char plot[] = {"plot"};
1984 static Display *mydisplay = NULL;
1985 static Window mywindow = -1;
1986 int dorefresh = 1;
1987 GC mygc;
1988 XEvent myevent;
1989 XSizeHints myhint;
1990 XWindowAttributes mywattributes;
1991 int myscreen;
1992 unsigned long myforeground,mybackground;
1993 int done;
1994
1995 ui_UsingGUI();
1996
1997 /* open the display */
1998 if (mydisplay == NULL) {
1999 mydisplay = XOpenDisplay("");
2000 if(!mydisplay)
2001 error("Unable to open display");
2002 dorefresh = 0;
2003 }
2004 myscreen = DefaultScreen(mydisplay);
2005 mybackground = WhitePixel(mydisplay,myscreen);
2006 myforeground = BlackPixel(mydisplay,myscreen);
2007
2008 myhint.x = 100;
2009 myhint.y = 100;
2010 myhint.width = (int)(DEFWWIDTH * ratio + 0.5);
2011 myhint.height = DEFWHEIGHT;
2012 myhint.flags = PPosition | USSize;
2013
2014 debugf(("Opened display OK\n"));
2015
2016 if (mywindow == -1) {
2017 debugf(("Opening window\n"));
2018 mywindow = XCreateSimpleWindow(mydisplay,
2019 DefaultRootWindow(mydisplay),
2020 myhint.x,myhint.y,myhint.width,myhint.height,
2021 5, myforeground,mybackground);
2022 XSetStandardProperties(mydisplay,mywindow,plot,plot,None,
2023 NULL,0, &myhint);
2024 }
2025
2026 mygc = XCreateGC(mydisplay,mywindow,0,0);
2027 XSetBackground(mydisplay,mygc,mybackground);
2028 XSetForeground(mydisplay,mygc,myforeground);
2029
2030 XSelectInput(mydisplay,mywindow,
2031 KeyPressMask | ExposureMask | StructureNotifyMask);
2032
2033 if (dorefresh) {
2034 XExposeEvent ev;
2035
2036 ev.type = Expose;
2037 ev.display = mydisplay;
2038 ev.send_event = True;
2039 ev.window = mywindow;
2040 ev.x = 0;
2041 ev.y = 0;
2042 ev.width = myhint.width;
2043 ev.height = myhint.height;
2044 ev.count = 0;
2045
2046 XClearWindow(mydisplay, mywindow);
2047 XSendEvent(mydisplay, mywindow, False, ExposureMask, (XEvent *)&ev);
2048
2049 } else {
2050 if (pd.dowait > 0) {
2051 XMapRaised(mydisplay,mywindow);
2052 debugf(("Raised window\n"));
2053 }
2054 }
2055
2056 /* Main event loop */
2057 debugf(("About to enter main loop\n"));
2058 done = 0;
2059 while(done == 0) {
2060 XNextEvent(mydisplay,&myevent);
2061 switch(myevent.type) {
2062 case Expose:
2063 if(myevent.xexpose.count == 0) { /* Repare the exposed region */
2064 XGetWindowAttributes(mydisplay, mywindow, & mywattributes);
2065 /* Setup the plot info structure for this drawing */
2066 pd.sx = mywattributes.x;
2067 pd.sy = mywattributes.y;
2068 pd.sw = mywattributes.width;
2069 pd.sh = mywattributes.height;
2070 pd.scx = (pd.sw - 10)/(pd.mxx - pd.mnx);
2071 pd.scy = (pd.sh - 10)/(pd.mxy - pd.mny);
2072
2073 DoPlot(mydisplay,mywindow, mygc, &pd);
2074
2075 if (pd.dowait <= 0) { /* Don't wait */
2076 if (pd.dowait < 0)
2077 sleep(-pd.dowait);
2078 debugf(("Not waiting, so set done=1\n"));
2079 done = 1;
2080 }
2081 }
2082 break;
2083 case MappingNotify:
2084 XRefreshKeyboardMapping(&myevent.xmapping);
2085 break;
2086 case KeyPress:
2087 debugf(("Got a button press\n"));
2088 done = 1;
2089 break;
2090 }
2091 }
2092 debugf(("About to close display\n"));
2093 XFreeGC(mydisplay,mygc);
2094 // XDestroyWindow(mydisplay,mywindow);
2095 // XCloseDisplay(mydisplay);
2096 debugf(("finished\n"));
2097 }
2098 return 0;
2099 }
2100
2101 /* Draw X axis grid lines */
2102 void
xtick(Display * mydisplay,Window mywindow,GC mygc,plot_info * pdp,double x,char * lab)2103 xtick(
2104 Display *mydisplay,
2105 Window mywindow,
2106 GC mygc,
2107 plot_info *pdp,
2108 double x, char *lab
2109 ) {
2110 int xx,yy;
2111
2112 xx = 10 + (int)((x - pdp->mnx) * pdp->scx + 0.5);
2113 yy = pdp->sh - 10;
2114
2115 XDrawLine(mydisplay, mywindow, mygc, xx, yy, xx, 0);
2116 XDrawImageString(mydisplay, mywindow, mygc, xx-6, yy, lab, strlen(lab));
2117 }
2118
2119 /* Draw Y axis grid lines */
2120 void
ytick(Display * mydisplay,Window mywindow,GC mygc,plot_info * pdp,double y,char * lab)2121 ytick(
2122 Display *mydisplay,
2123 Window mywindow,
2124 GC mygc,
2125 plot_info *pdp,
2126 double y, char *lab
2127 ) {
2128 int xx,yy;
2129
2130 xx = 5;
2131 yy = pdp->sh - 10 - (int)((y - pdp->mny) * pdp->scy + 0.5);
2132
2133 XDrawLine(mydisplay, mywindow, mygc, xx, yy, pdp->sw, yy);
2134 XDrawImageString(mydisplay, mywindow, mygc, xx, yy+4, lab, strlen(lab));
2135 }
2136
2137 void
loose_label(Display * mydisplay,Window mywindow,GC mygc,plot_info * pdp,double min,double max,void (* pfunc)(Display * mydisplay,Window mywindow,GC mygc,plot_info * pdp,double,char *))2138 loose_label(
2139 Display *mydisplay,
2140 Window mywindow,
2141 GC mygc,
2142 plot_info *pdp,
2143 double min, double max,
2144 void (*pfunc)(Display *mydisplay, Window mywindow, GC mygc, plot_info *pdp, double, char *)
2145 ) {
2146 char str[6], temp[20];
2147 int nfrac;
2148 double d;
2149 double graphmin, graphmax;
2150 double range,x;
2151
2152 range = nicenum(min-max,0);
2153 d = nicenum(range/(NTICK-1),1);
2154 graphmin = floor(min/d) * d;
2155 graphmax = ceil(max/d) * d;
2156 nfrac = (int)MAX(-floor(log10(d)),0);
2157 sprintf(str,"%%.%df", nfrac);
2158 for (x = graphmin; x < graphmax + 0.5 * d; x += d) {
2159 sprintf(temp,str,x);
2160 pfunc(mydisplay, mywindow, mygc, pdp, x, temp);
2161 }
2162 }
2163
2164 void
DoPlot(Display * mydisplay,Window mywindow,GC mygc,plot_info * pdp)2165 DoPlot(
2166 Display *mydisplay,
2167 Window mywindow,
2168 GC mygc,
2169 plot_info *pdp
2170 ) {
2171 int i, j;
2172 int lx,ly; /* Last x,y */
2173 char dash_list[2] = {5, 1};
2174 Colormap mycmap;
2175 XColor col;
2176
2177 mycmap = DefaultColormap(mydisplay, 0);
2178 col.red = col.green = col.blue = 150 * 256;
2179 XAllocColor(mydisplay, mycmap, &col);
2180 XSetForeground(mydisplay,mygc, col.pixel);
2181
2182 /* Set dashed lines for axes */
2183 XSetLineAttributes(mydisplay, mygc, 1, LineOnOffDash, CapButt, JoinBevel);
2184 XSetDashes(mydisplay, mygc, 0, dash_list, 2);
2185 // ~~ doesn't seem to work. Why ?
2186
2187 /* Plot horizontal axis */
2188 if (pdp->revx)
2189 loose_label(mydisplay, mywindow, mygc, pdp, pdp->mxx, pdp->mnx, xtick);
2190 else
2191 loose_label(mydisplay, mywindow, mygc, pdp, pdp->mnx, pdp->mxx, xtick);
2192
2193 /* Plot vertical axis */
2194 loose_label(mydisplay, mywindow, mygc, pdp, pdp->mny, pdp->mxy, ytick);
2195
2196 if (pdp->graph) { /* Up to 10 graphs */
2197 for (j = MXGPHS-1; j >= 0; j--) {
2198 double *yp = pdp->yy[j];
2199
2200 if (yp == NULL)
2201 continue;
2202
2203 col.red = gcolors[j][0] * 256;
2204 col.green = gcolors[j][1] * 256;
2205 col.blue = gcolors[j][2] * 256;
2206 XAllocColor(mydisplay, mycmap, &col);
2207 XSetForeground(mydisplay,mygc, col.pixel);
2208 XSetLineAttributes(mydisplay, mygc, ILTHICK, LineSolid, CapButt, JoinBevel);
2209
2210 lx = (int)((pdp->x1[0] - pdp->mnx) * pdp->scx + 0.5);
2211 ly = (int)(( yp[0] - pdp->mny) * pdp->scy + 0.5);
2212
2213 for (i = 0; i < pdp->n; i++) {
2214 int cx,cy;
2215 cx = (int)((pdp->x1[i] - pdp->mnx) * pdp->scx + 0.5);
2216 cy = (int)(( yp[i] - pdp->mny) * pdp->scy + 0.5);
2217
2218 XDrawLine(mydisplay, mywindow, mygc, 10 + lx, pdp->sh - 10 - ly, 10 + cx, pdp->sh - 10 - cy);
2219 if (pdp->flags & PLOTF_GRAPHCROSSES) {
2220 XDrawLine(mydisplay, mywindow, mygc, 10 + cx - 5, pdp->sh - 10 - cy - 5, 10 + cx + 5, pdp->sh - 10 - cy + 5);
2221 XDrawLine(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy - 5, 10 + cx - 5, pdp->sh - 10 - cy + 5);
2222 }
2223 lx = cx;
2224 ly = cy;
2225 }
2226 }
2227
2228 } else { /* Vectors */
2229
2230 col.red = col.green = col.blue = 0 * 256;
2231 XAllocColor(mydisplay, mycmap, &col);
2232 XSetForeground(mydisplay,mygc, col.pixel);
2233 XSetLineAttributes(mydisplay, mygc, ILTHICK, LineSolid, CapButt, JoinBevel);
2234
2235 for (i = 0; i < pdp->n; i++) {
2236 int cx,cy;
2237
2238 lx = (int)((pdp->x1[i] - pdp->mnx) * pdp->scx + 0.5);
2239 ly = (int)((pdp->yy[0][i] - pdp->mny) * pdp->scy + 0.5);
2240
2241 cx = (int)((pdp->x2[i] - pdp->mnx) * pdp->scx + 0.5);
2242 cy = (int)((pdp->yy[1][i] - pdp->mny) * pdp->scy + 0.5);
2243
2244 /* Vector */
2245 XDrawLine(mydisplay, mywindow, mygc, 10 + lx, pdp->sh - 10 - ly, 10 + cx, pdp->sh - 10 - cy);
2246
2247 if (pdp->flags & PLOTF_VECCROSSES) {
2248 /* Cross at end of vector */
2249 XDrawLine(mydisplay, mywindow, mygc, 10 + cx - 5, pdp->sh - 10 - cy - 5, 10 + cx + 5, pdp->sh - 10 - cy + 5);
2250 XDrawLine(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy - 5, 10 + cx - 5, pdp->sh - 10 - cy + 5);
2251 }
2252
2253 if (pdp->ntext != NULL)
2254 XDrawImageString(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy + 7,
2255 pdp->ntext[i], strlen(pdp->ntext[i]));
2256 }
2257 }
2258
2259 /* Extra points */
2260 if (pdp->x7 != NULL && pdp->y7 != NULL && pdp->m > 0 ) {
2261 col.red = 210 * 256; col.green = 150 * 256; col.blue = 0 * 256;
2262 XAllocColor(mydisplay, mycmap, &col);
2263 XSetForeground(mydisplay,mygc, col.pixel);
2264 XSetLineAttributes(mydisplay, mygc, ILTHICK, LineSolid, CapButt, JoinBevel);
2265
2266 for (i = 0; i < pdp->m; i++) {
2267 lx = (int)((pdp->x7[i] - pdp->mnx) * pdp->scx + 0.5);
2268 ly = (int)((pdp->y7[i] - pdp->mny) * pdp->scy + 0.5);
2269
2270 if (pdp->mcols != NULL) {
2271 col.red = (int)(pdp->mcols[i].rgb[0] * 65535.0 + 0.5);
2272 col.green = (int)(pdp->mcols[i].rgb[1] * 65535.0 + 0.5);
2273 col.blue = (int)(pdp->mcols[i].rgb[2] * 65535.0 + 0.5);
2274
2275 XAllocColor(mydisplay, mycmap, &col);
2276 XSetForeground(mydisplay,mygc, col.pixel);
2277
2278 }
2279 XDrawLine(mydisplay, mywindow, mygc, 10 + lx - 5, pdp->sh - 10 - ly,
2280 10 + lx + 5, pdp->sh - 10 - ly);
2281 XDrawLine(mydisplay, mywindow, mygc, 10 + lx, pdp->sh - 10 - ly - 5,
2282 10 + lx, pdp->sh - 10 - ly + 5);
2283
2284 if (pdp->mtext != NULL)
2285 XDrawImageString(mydisplay, mywindow, mygc, 10 + lx + 5, pdp->sh - 10 - ly - 7,
2286 pdp->mtext[i], strlen(pdp->mtext[i]));
2287 }
2288 }
2289
2290 /* Extra vectors */
2291 if (pdp->x8 != NULL && pdp->y8 != NULL && pdp->x9 != NULL && pdp->y9 && pdp->o > 0 ) {
2292 col.red = 150 * 256; col.green = 255 * 256; col.blue = 255 * 256;
2293 XAllocColor(mydisplay, mycmap, &col);
2294 XSetForeground(mydisplay,mygc, col.pixel);
2295 XSetLineAttributes(mydisplay, mygc, ILTHICK, LineSolid, CapButt, JoinBevel);
2296
2297 for (i = 0; i < pdp->o; i++) {
2298 int cx,cy;
2299
2300 lx = (int)((pdp->x8[i] - pdp->mnx) * pdp->scx + 0.5);
2301 ly = (int)((pdp->y8[i] - pdp->mny) * pdp->scy + 0.5);
2302
2303 cx = (int)((pdp->x9[i] - pdp->mnx) * pdp->scx + 0.5);
2304 cy = (int)((pdp->y9[i] - pdp->mny) * pdp->scy + 0.5);
2305
2306 if (pdp->ocols != NULL) {
2307 col.red = (int)(pdp->ocols[i].rgb[0] * 65535.0 + 0.5);
2308 col.green = (int)(pdp->ocols[i].rgb[1] * 65535.0 + 0.5);
2309 col.blue = (int)(pdp->ocols[i].rgb[2] * 65535.0 + 0.5);
2310
2311 XAllocColor(mydisplay, mycmap, &col);
2312 XSetForeground(mydisplay,mygc, col.pixel);
2313
2314 }
2315
2316 XDrawLine(mydisplay, mywindow, mygc, 10 + lx, pdp->sh - 10 - ly, 10 + cx, pdp->sh - 10 - cy);
2317 }
2318 }
2319 }
2320
2321 #endif /* UNIX + X11 */
2322 #endif /* !NT */
2323 /***********************************************************************/
2324
2325
2326 /* Nice graph labeling functions */
2327
2328 #define expt(a,n) pow(a,(double)(n))
2329
nicenum(double x,int round)2330 double nicenum(double x, int round) {
2331 int ex;
2332 double f;
2333 double nf;
2334 // printf("nocenum called with %f and %d\n",x,round);
2335 if (x < 0.0)
2336 x = -x;
2337 ex = (int)floor(log10(x));
2338 // printf("ex = %d\n",ex);
2339 f = x/expt(10.0,ex);
2340 // printf("f = %f\n",f);
2341 if (round) {
2342 if (f < 1.5) nf = 1.0;
2343 else if (f < 3.0) nf = 2.0;
2344 else if (f < 7.0) nf = 5.0;
2345 else nf = 10.0;
2346 } else {
2347 if (f < 1.0) nf = 1.0;
2348 else if (f < 2.0) nf = 2.0;
2349 else if (f < 5.0) nf = 5.0;
2350 else nf = 10.0;
2351 }
2352 // printf("nf = %f\n",nf);
2353 // printf("about to return %f\n",(nf * expt(10.0, ex)));
2354 return (nf * expt(10.0, ex));
2355 }
2356
2357 /* ---------------------------------------------------------------- */
2358 #ifdef STANDALONE_TEST
2359 /* test code */
2360
2361 //#include <windows.h>
2362 //#include <stdio.h>
2363 #include <fcntl.h>
2364 //#include <io.h>
2365
2366
2367 #ifdef NEVER
2368 /* Append debugging string to log.txt */
dprintf(char * fmt,...)2369 static void dprintf(char *fmt, ...) {
2370 FILE *fp = NULL;
2371 if ((fp = fopen("log.txt", "a+")) != NULL) {
2372 va_list args;
2373 va_start(args, fmt);
2374 vfprintf(fp, fmt, args);
2375 fflush(fp);
2376 fclose(fp);
2377 va_end(args);
2378 }
2379 }
2380 #endif // NEVER
2381
2382 #ifdef NEVER /* Other non-working enable console output code */
2383 {
2384 /* This clever code have been found at:
2385 Adding Console I/O to a Win32 GUI App
2386 Windows Developer Journal, December 1997
2387 http://dslweb.nwnexus.com/~ast/dload/guicon.htm
2388 Andrew Tucker's Home Page */
2389
2390 /* This is not so clever, since it doesn't work... */
2391
2392 // redirect unbuffered STDOUT to the console
2393 long lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
2394 int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
2395 FILE *fp = _fdopen(hConHandle, "w");
2396 *stdout = *fp;
2397 setvbuf(stdout, NULL, _IONBF, 0);
2398
2399 // redirect unbuffered STDIN to the console
2400 lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
2401 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
2402 fp = _fdopen( hConHandle, "r" );
2403 *stdin = *fp;
2404 setvbuf(stdin, NULL, _IONBF, 0);
2405
2406 // redirect unbuffered STDERR to the console
2407 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
2408 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
2409 fp = _fdopen( hConHandle, "w" );
2410 *stderr = *fp;
2411 setvbuf(stderr, NULL, _IONBF, 0);
2412
2413
2414 }
2415 #endif // NEVER
2416
2417 #ifdef NEVER
2418 // ~~~~~~~~~~~~~
2419 // AllocConsole();
2420 {
2421 ULONG pbi[6];
2422 ULONG ulSize = 0;
2423 LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle,
2424 ULONG ProcessInformationClass,
2425 PVOID ProcessInformation,
2426 ULONG ProcessInformationLength,
2427 PULONG ReturnLength);
2428
2429 BOOL (WINAPI *AttachConsole)(DWORD dwProcessId);
2430
2431 *(FARPROC *)&NtQueryInformationProcess =
2432 GetProcAddress(LoadLibraryA("NTDLL.DLL"), "NtQueryInformationProcess");
2433 if(NtQueryInformationProcess) {
2434 printf("~1 found NtQueryInformationProcess\n"); fflush(stdout);
2435 if(NtQueryInformationProcess(GetCurrentProcess(), 0,
2436 &pbi, sizeof(pbi), &ulSize) >= 0 && ulSize == sizeof(pbi)) {
2437 printf("~1 NtQueryInformationProcess suceeded\n"); fflush(stdout);
2438
2439 *(FARPROC *)&AttachConsole =
2440 GetProcAddress(LoadLibraryA("kernel32.dll"), "AttachConsole");
2441
2442 if (AttachConsole) {
2443 printf("~1 found AttachConsole\n"); fflush(stdout);
2444 AttachConsole(pbi[5]);
2445 printf("~1 about to freopen CONNOUT\n"); fflush(stdout);
2446 freopen("CONOUT$","wb",stdout);
2447 } else {
2448 printf("~1 failed to find AttachConsole\n"); fflush(stdout);
2449 }
2450 }
2451 }
2452 // AttachConsole(ID ATTACH_PARENT_CONSOLE); // Should work on XP ??
2453
2454 /* i mean OpenConsoleW - you are as picky as i am - its
2455 ordinal=519 and it is exported by name; the header(s)
2456 do not include it, which tells me there's got to be a
2457 reason for that.
2458 */
2459 }
2460 // ~~~~~~~~~~~~~
2461 #endif // NEVER
2462
2463
main(int argc,char * argv[])2464 int main(int argc, char *argv[]) {
2465 double x[10] = {0.0, 0.5, 0.7, 1.0};
2466 double y1[10] = {0.0, 0.5, 0.7, 1.0};
2467 double y2[10] = {0.9, 0.8, 1.4, 1.2};
2468 double y3[10] = {0.1, 0.8, 0.7, -0.1};
2469
2470 double Bx1[10] = {0.0, 0.5, 0.9, 0.5};
2471 double By1[10] = {0.0, 0.3, 1.2, 0.2};
2472 double Bx2[10] = {0.1, 0.8, 0.1, 0.2};
2473 double By2[10] = {0.1, 1.8, 2.0, 0.5};
2474
2475 double Bx3[10] = {0.8, 0.4, 1.3, 0.5, 0.23};
2476 double By3[10] = {0.5, 1.3, 0.4, 0.7, 0.77};
2477
2478 plot_col mcols[5] = {
2479 { 1.0, 0.0, 0.0 },
2480 { 0.0, 1.0, 0.0 },
2481 { 0.0, 0.0, 1.0 },
2482 { 0.6, 0.6, 0.6 },
2483 { 1.0, 1.0, 0.0 } };
2484
2485 char *ntext[5] = { "A", "B", "C", "D" };
2486 char *mtext[5] = { "10", "20", "30", "40", "50" };
2487
2488 printf("Doing first plot\n");
2489 if (do_plot(x,y1,y2,y3,4) < 0)
2490 printf("Error - do_plot returned -1!\n");
2491
2492 /* Try a second plot */
2493 printf("Doing second plot\n");
2494 x[2] = 0.55;
2495 if (do_plot(x,y2,y3,y1,3) < 0)
2496 printf("Error - do_plot returned -1!\n");
2497
2498 /* Try vectors */
2499 printf("Doing vector plot\n");
2500 if (do_plot_vec(0.0, 1.4, 0.0, 2.0, Bx1, By1, Bx2, By2, 4, 1, Bx3, By3, NULL, NULL, 5))
2501 printf("Error - do_plot_vec returned -1!\n");
2502
2503 printf("Doing vector plot with colors and notation\n");
2504 if (do_plot_vec(0.0, 1.4, 0.0, 2.0, Bx1, By1, Bx2, By2, 4, 1, Bx3, By3, mcols, mtext, 5))
2505 printf("Error - do_plot_vec returned -1!\n");
2506
2507 printf("Doing vector plot with colors and notation + extra vectors\n");
2508 if (do_plot_vec2(0.0, 1.4, 0.0, 2.0, Bx1, By1, Bx2, By2, ntext, 4, 1, Bx3, By3, mcols, mtext, 5,
2509 x,y1,y2,y3,mcols,4))
2510 printf("Error - do_plot_vec returned -1!\n");
2511
2512 printf("We're done\n");
2513 return 0;
2514 }
2515
2516 #endif /* STANDALONE_TEST */
2517 /* ---------------------------------------------------------------- */
2518
2519