1 /*
2 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 - Neither the name of The Numerical ALgorithms Group Ltd. nor the
18 names of its contributors may be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #define _VIEWPORT2D_C
35 #include "fricas_c_macros.h"
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <math.h>
42 #include <X11/X.h>
43 #include <X11/Xlib.h>
44 #include <X11/Xutil.h>
45 #include <limits.h>
46
47 #define NotPoint (SHRT_MAX)
48 #define eqNANQ(x) (x == NotPoint)
49
50 #include "header2.h"
51
52 #include "all_2d.H1"
53 #include "Gfun.H1"
54 #include "util.H1"
55 #include "XSpadFill.H1"
56
57 #include "strutil.h"
58
59 #define rint(z) ((int)(z))
60
61 Atom wm_delete_window;
62
63
64 /***************************
65 *** void writeTitle() ***
66 ***************************/
67
68 void
writeTitle(void)69 writeTitle(void)
70 {
71
72 int strlength;
73 XWindowAttributes attribInfo;
74
75 XGetWindowAttributes(dsply,viewport->titleWindow,&attribInfo);
76 if (mono) GSetForeground(anotherGC,(float)foregroundColor,Xoption);
77 else GSetForeground(anotherGC,(float)titleColor,Xoption);
78 XClearWindow(dsply,viewport->titleWindow); /* it's behind the viewWindow */
79 strlength = strlen(viewport->title);
80 GDrawImageString(anotherGC,viewport->titleWindow,
81 centerX(anotherGC,viewport->title,strlength,attribInfo.width),
82 15,viewport->title,strlength,Xoption);
83
84 }
85
86 float
calcStartX(XWindowAttributes vwInfo)87 calcStartX(XWindowAttributes vwInfo)
88 {
89 return vwInfo.width *
90 ((graphArray[0].originX - graphStateArray[0].centerX) *
91 graphStateArray[0].scaleX + 0.5);
92 }
93
94 float
calcStartY(XWindowAttributes vwInfo,float aspectR)95 calcStartY(XWindowAttributes vwInfo, float aspectR)
96 {
97 return vwInfo.height * aspectR *
98 (1 - ((graphArray[0].originY*aspectR -
99 graphStateArray[0].centerY) *
100 graphStateArray[0].scaleY + 0.5*aspectR));
101 }
102
103 /* Globals:
104 unitGC
105 graphArray
106 */
107
108 void
do_x_tick(Window vw,int jj,int ii,XWindowAttributes vwInfo,int dFlag,int descent)109 do_x_tick(Window vw, int jj, int ii, XWindowAttributes vwInfo,
110 int dFlag, int descent)
111 {
112 char aunit[20];
113 int strlength;
114 int halflength;
115 /* ticks stuck to viewport*/
116 GDrawLine(unitGC, vw, jj, vwInfo.height - 8,
117 jj, vwInfo.height - 4, dFlag);
118
119 fricas_sprintf_to_buf1(aunit, "%0.3g", ii*graphArray[0].spadUnitX);
120 strlength = strlen(aunit);
121 halflength = XTextWidth(unitFont,aunit,strlength)/2;
122
123 if (dFlag == Xoption) {
124 GDrawImageString(unitGC, vw, jj - halflength,
125 vwInfo.height - 8 - descent,
126 aunit, strlength, dFlag);
127 }
128 if (dFlag == PSoption) {
129 GDrawImageString(unitGC, vw, jj - (strlength*3),
130 vwInfo.height - 14,
131 aunit, strlength, dFlag);
132 /* these are "eyeball" parameters for the given PS font */
133 }
134 }
135
136 /* Globals:
137 unitGC
138 graphArray
139 unitFont
140 */
141
142 void
do_y_tick(Window vw,int jj,int ii,XWindowAttributes vwInfo,int dFlag,int charlength)143 do_y_tick(Window vw, int jj, int ii, XWindowAttributes vwInfo,
144 int dFlag, int charlength)
145 {
146 char aunit[20];
147 int strlength;
148 int halflength;
149 int dummyInt, ascent, descent;
150 XCharStruct overall;
151
152 /* ticks stuck to viewport*/
153 /* on the right */
154 #if 0
155 /* on the right */
156 GDrawLine(unitGC, vw, vwInfo.width-6, jj,
157 vwInfo.width-2, jj, dFlag);
158 #endif
159 /* on the left */
160 GDrawLine(unitGC, vw, 2, jj,
161 6, jj, dFlag);
162
163 fricas_sprintf_to_buf1(aunit, "%0.3g", ii*graphArray[0].spadUnitY);
164 strlength = strlen(aunit);
165 XTextExtents(unitFont, aunit, strlength, &dummyInt,
166 &ascent, &descent, &overall);
167 halflength = overall.width;
168 if (dFlag == Xoption) {
169 #if 0
170 /* on the right */
171 GDrawImageString(unitGC, vw, vwInfo.width - halflength - 6 - descent,
172 jj + ascent/2, aunit, strlength, dFlag);
173 #endif
174 /* on the left */
175 GDrawImageString(unitGC, vw, 8 + charlength/2,
176 jj + ascent/2 , aunit, strlength, dFlag);
177 }
178 if (dFlag == PSoption) {
179 #if 0
180 /* on the right */
181 GDrawImageString(unitGC, vw, vwInfo.width - 6 - (strlength*6),
182 jj + 4, aunit, strlength, dFlag);
183 #endif
184 /* on the left */
185 GDrawImageString(unitGC, vw, 8, jj + 4,
186 aunit, strlength, dFlag);
187 /* these are "eyeball" parameters for the given PS font */
188 }
189 }
190
191 /********************************/
192 /*** void drawTheViewport() ***/
193 /********************************/
194
195 void
drawTheViewport(int dFlag)196 drawTheViewport(int dFlag) /* display flag: X, PS,... */
197 {
198
199 Window vw;
200 XWindowAttributes vwInfo;
201 pointListStruct *aList;
202 pointStruct *aPoint;
203 XPoint *anXPoint,*tempXpt;
204 XArc *anXarc;
205 Vertex *anX10Point;
206 float jj,diffX, diffY, tickStart,oneTickUnit;
207 int i,j,k,ii,halfSize;
208 int charlength, halfheight;
209 int ptX,ptY,ptX1,ptY1,clipped, clipped1;
210 int xAxis,yAxis,dummyInt, ascent, descent;
211 int unitWidth,boxX,boxY,boxW,boxH;
212 XCharStruct overall;
213
214 drawMore = yes;
215 vw = viewport->viewWindow;
216 XGetWindowAttributes(dsply,vw,&vwInfo);
217 aspectR = (float)vwInfo.width/(float)vwInfo.height;
218
219 XTextExtents(unitFont,"o",1,&dummyInt,&ascent,&descent,&overall);
220 halfheight = (ascent + descent) / 2;
221
222 /* Calculate various factors for use in projection. */
223 /* Scale the plot, so that the scaling between the axes remains
224 constant and fits within the smaller of the two dimensions. */
225
226 charlength = overall.width;
227
228 if (dFlag==Xoption) XClearWindow(dsply,vw);
229
230 for (i=0; i<maxGraphs; i++) {
231
232 if ((graphArray[i].key) && (graphStateArray[i].showing)) {
233
234 /* Scale y coordinate dimensions relative to viewport aspect ratio. */
235
236 graphArray[i].yNorm = 1.0/((graphArray[i].ymax-graphArray[i].ymin) *
237 aspectR);
238 graphArray[i].originY = -graphArray[i].ymin*graphArray[i].yNorm
239 - 0.5/aspectR;
240 graphArray[i].unitY = graphArray[i].spadUnitY*graphArray[i].yNorm;
241
242 xAxis = rint(vwInfo.width *
243 ((graphArray[0].originX - graphStateArray[0].centerX) *
244 graphStateArray[0].scaleX + 0.5));
245 yAxis= rint(vwInfo.height * aspectR *
246 (1 - ((graphArray[0].originY*aspectR -
247 graphStateArray[0].centerY) *
248 graphStateArray[0].scaleY + 0.5*aspectR )));
249
250 if (graphStateArray[i].axesOn) {
251 if (dFlag==Xoption) /* do only for X, ps uses default of black */
252 GSetForeground(globalGC1,
253 (float)monoColor(graphStateArray[i].axesColor),
254 dFlag);
255
256 if ((yAxis >=0) && (yAxis <= vwInfo.height))
257 GDrawLine(globalGC1,vw,
258 0,yAxis,
259 vwInfo.width,yAxis,
260 dFlag);
261 if ((xAxis >=0) && (xAxis <= vwInfo.width))
262 GDrawLine(globalGC1,vw,
263 xAxis,0,
264 xAxis,vwInfo.height,
265 dFlag);
266 }
267
268
269 tempXpt = anXPoint = xPointsArray[i].xPoint;
270 anX10Point = xPointsArray[i].x10Point;
271 anXarc = xPointsArray[i].arc;
272
273 for (j=0,aList=graphArray[i].listOfListsOfPoints;
274 (j<graphArray[i].numberOfLists);
275 j++, aList++) {
276
277 for (k=0,aPoint=aList->listOfPoints;
278 (k<aList->numberOfPoints);
279 k++,aPoint++) {
280
281 if (graphStateArray[i].scaleX > 99.0)
282 graphStateArray[i].scaleX = 99.0;
283 if (graphStateArray[i].scaleY > 99.0)
284 graphStateArray[0].scaleY = 99.0;
285 if (i > 0) {
286 if (isNaN(aPoint->x)) {
287 anXPoint->x = anX10Point->x = NotPoint;
288 }
289 else {
290 diffX = graphArray[i].xmax-graphArray[i].xmin;
291 anXPoint->x = anX10Point->x = vwInfo.width *
292 ((aPoint->x * diffX/(graphArray[0].xmax-graphArray[0].xmin)
293 + (graphArray[0].originX - graphArray[i].originX*diffX /
294 (graphArray[0].xmax-graphArray[0].xmin))
295 - graphStateArray[0].centerX)*graphStateArray[i].scaleX+0.5);
296 }
297 if (isNaN(aPoint->y)) {
298 anXPoint->y = anX10Point->y = NotPoint;
299 }
300 else {
301 diffY = graphArray[i].ymax-graphArray[i].ymin;
302 anXPoint->y = anX10Point->y = vwInfo.height * aspectR *
303 (1 - ((aPoint->y * diffY/(graphArray[0].ymax-graphArray[0].ymin)
304 + (graphArray[0].originY - graphArray[i].originY* diffY/
305 (graphArray[0].ymax-graphArray[0].ymin))*aspectR
306 - graphStateArray[0].centerY) *
307 graphStateArray[i].scaleY + 0.5*aspectR));
308 }
309 } else {
310 if (isNaN(aPoint->x)) {
311 anXPoint->x = anX10Point->x = NotPoint;
312 }
313 else {
314 anXPoint->x = anX10Point->x = vwInfo.width *
315 ((aPoint->x - graphStateArray[i].centerX) *
316 graphStateArray[i].scaleX + 0.5);
317 }
318 if (isNaN(aPoint->y)) {
319 anXPoint->y = anX10Point->y = NotPoint;
320 }
321 else {
322 anXPoint->y = anX10Point->y = vwInfo.height * aspectR *
323 (1 - ((aPoint->y - graphStateArray[i].centerY) *
324 graphStateArray[i].scaleY + 0.5*aspectR));
325 }
326 }
327
328 /* first or last point */
329 if (k == 0 || k == (aList->numberOfPoints - 1)) {
330 anX10Point->flags = 0;
331 } else {
332 anX10Point->flags = VertexCurved;
333 }
334
335 anXPoint++;
336 anX10Point++;
337 anXarc++;
338 } /* for aPoint in pointList */
339
340 aPoint--; /* make it legal, the last one*/
341 if (graphStateArray[i].connectOn || graphStateArray[i].pointsOn) {
342 halfSize = aList->pointSize/2;
343 ptX = tempXpt->x;
344 ptY = tempXpt->y;
345 clipped = ptX > vwInfo.x && ptX < vwInfo.width &&
346 ptY > 0 && ptY < vwInfo.height;
347 if (graphStateArray[i].pointsOn) {
348 if (dFlag==Xoption) {
349 if (mono) {
350 GSetForeground(globalGC1,
351 (float)monoColor((int)(aPoint->hue)),
352 dFlag);
353 } else {
354 GSetForeground(globalGC1,
355 (float)XSolidColor((int)(aPoint->hue),
356 (int)(aPoint->shade)),
357 dFlag);
358 }
359 }
360 if (clipped && !eqNANQ(ptX) && !eqNANQ(ptY))
361 GFillArc(globalGC1,vw,ptX-halfSize,
362 ptY-halfSize,aList->pointSize,aList->pointSize,
363 0,360*64, dFlag);
364
365 } /* if points on */
366 for (ii=0, aPoint=aList->listOfPoints;
367 ii<aList->numberOfPoints;
368 ++ii, ++tempXpt, ++aPoint) {
369 ptX1 = tempXpt->x;
370 ptY1 = tempXpt->y;
371 clipped1 = ptX1 > vwInfo.x && ptX1 < vwInfo.width &&
372 ptY1 > 0 && ptY1 < vwInfo.height;
373 if (graphStateArray[i].connectOn) {
374 if (dFlag==Xoption) {
375 if (mono) {
376 GSetForeground(globalGC1,
377 (float)monoColor((int)(aList->lineColor-1)/5),
378 dFlag);
379 } else {
380 GSetForeground(globalGC1,
381 (float)XSolidColor((int)(aList->lineColor-1)/5,
382 (int)((aList->lineColor-1)%5)/2),
383 dFlag);
384 }
385 } /* if X */
386 if ((clipped || clipped1) && !eqNANQ(ptX) && !eqNANQ(ptY) &&
387 !eqNANQ(ptX1) && !eqNANQ(ptY1))
388 GDrawLine(globalGC1,vw,
389 ptX,ptY,ptX1,ptY1,
390 dFlag);
391 } /* if lines on */
392 if (graphStateArray[i].pointsOn) {
393 if (dFlag==Xoption) {
394 if (mono) {
395 GSetForeground(globalGC1,
396 (float)monoColor((int)(aPoint->hue)),
397 dFlag);
398 } else {
399 GSetForeground(globalGC1,
400 (float)XSolidColor((int)(aPoint->hue),
401 (int)(aPoint->shade)),
402 dFlag);
403 }
404 }
405 if (clipped1 && !eqNANQ(ptX1) && !eqNANQ(ptY1))
406 GFillArc(globalGC1,vw,ptX1-halfSize,
407 ptY1-halfSize,aList->pointSize,aList->pointSize,
408 0,360*64, dFlag);
409 } /* if points on */
410 ptX = ptX1; ptY = ptY1; clipped = clipped1;
411 } /* for all points */
412 } /* if points or lines on */
413
414 if (graphStateArray[i].splineOn) { /* need spline color as well */
415 if (dFlag==Xoption) /* do only for X, ps uses default of black */
416 GSetForeground(globalGC1,
417 (float)monoColor(148),
418 dFlag);
419 boxX = vwInfo.width *
420 ((-0.5 - graphStateArray[i].centerX)*
421 graphStateArray[i].scaleX + 0.5);
422 boxY = vwInfo.height * aspectR *
423 (1 - ((0.5 - graphStateArray[i].centerY)*
424 graphStateArray[i].scaleY + 0.5*aspectR));
425
426 boxW = graphStateArray[i].scaleX * vwInfo.width + 1;
427 boxH = graphStateArray[i].scaleY * vwInfo.height * aspectR + 1;
428
429 GDrawRectangle(globalGC1,vw,
430 boxX,boxY,boxW,boxH,
431 dFlag);
432 }
433
434 tempXpt = anXPoint;
435 } /* for a aList in listofListsOfPoints */
436 if (graphStateArray[i].unitsOn) {
437 /* do only for X, ps uses default of black */
438 if (dFlag==Xoption)
439 GSetForeground(unitGC,
440 (float)monoColor(graphStateArray[i].unitsColor),
441 dFlag);
442
443 tickStart = calcStartX(vwInfo);
444 oneTickUnit = vwInfo.width*graphArray[0].unitX*
445 graphStateArray[0].scaleX;
446
447 /* ticks along the positive X axis */
448
449 unitWidth = 5*overall.width; /* limit on acceptable separation : 5 chars */
450 k = floor(unitWidth/oneTickUnit) +1; /* get skipping integer */
451 for (ii=0, jj = tickStart;
452 jj < vwInfo.width;
453 ii = ii + k, jj = tickStart + ii*oneTickUnit) {
454 if (jj >= 0) {
455 do_x_tick(vw, (int)rint(jj), ii, vwInfo, dFlag, descent);
456 }
457
458 }
459 /* ticks along the negative X axis */
460 for (ii=-k,jj=tickStart - k*oneTickUnit;
461 jj > 0;
462 ii = ii - k, jj = tickStart + ii*oneTickUnit) {
463 if (jj <= vwInfo.width) {
464 do_x_tick(vw, (int)rint(jj), ii, vwInfo, dFlag, descent);
465 }
466 }
467
468 tickStart = calcStartY(vwInfo, aspectR);
469 oneTickUnit = -vwInfo.height * aspectR * graphArray[0].unitY *
470 aspectR * graphStateArray[0].scaleY;
471
472 /* ticks along the positive Y axis */
473 unitWidth = 2*(ascent+descent); /* limit of acceptable separation */
474 k = floor(unitWidth/fabs(oneTickUnit)) +1; /* get skipping integer */
475 for (ii=0,jj = tickStart;
476 jj > 0;
477 ii = ii + k, jj = tickStart + ii*oneTickUnit) {
478 if (jj < vwInfo.height) {
479 do_y_tick(vw, (int)rint(jj), ii, vwInfo, dFlag, charlength);
480 }
481 }
482
483 /* ticks along the negative Y axis */
484
485 for (ii=(-k),jj = tickStart - k*oneTickUnit;
486 jj < vwInfo.height;
487 ii = ii - k, jj = tickStart + ii*oneTickUnit) {
488 if (jj > 0) {
489 do_y_tick(vw, (int)rint(jj), ii, vwInfo, dFlag, charlength);
490 }
491 }
492 } /* if unitsOn */
493 } /* if graph i exists and is showing */
494 } /* for i in graphs */
495
496
497 if (dFlag==Xoption) {
498 if (!followMouse) {
499 /* no need to do this while autorepeating */
500 makeMessageFromData(queriedGraph);
501 writeControlMessage();
502 }
503 XFlush(dsply);
504 }
505
506 } /* drawViewport() */
507
508
509
510 /************************************
511 *** viewPoints *makeViewport() ***
512 ************************************/
513
514 viewPoints *
makeViewport(char * title,int vX,int vY,int vW,int vH,int showCP)515 makeViewport(char *title,int vX,int vY,int vW,int vH,int showCP)
516 {
517 Pixmap spadbits,spadmask;
518 XSetWindowAttributes viewAttrib;
519 XSizeHints titleSizeHints,viewSizeHints;
520 Window viewTitleWindow,viewGraphWindow;
521 XColor foreColor, backColor;
522
523 #ifdef DEBUG
524 fprintf(stderr,"view2D: About to make a viewport\n");
525 #endif
526
527 /* Create a viewport */
528 if (!(viewport = (viewPoints *)malloc(sizeof(viewPoints)))) {
529 fprintf(stderr,"Ran out of memory (malloc) trying to create a viewport.\n");
530 sleep(5);
531 exitWithAck(RootWindow(dsply,scrn),Window,-1);
532 }
533
534 #ifdef DEBUG
535 fprintf(stderr,"view2D: Made a viewport\n");
536 #endif
537
538 strcpy(viewport->title,title);
539
540 viewport->closing = no;
541 viewport->allowDraw = yes; /* just draw axes the first time around */
542 viewport->axesOn = axesON;
543 viewport->unitsOn = unitsON;
544 viewport->pointsOn = pointsON;
545 viewport->linesOn = connectON;
546 viewport->splineOn = splineON;
547
548 /**** Make the windows for the viewport ****/
549 viewAttrib.background_pixel = backgroundColor;
550 viewAttrib.border_pixel = foregroundColor;
551 viewAttrib.override_redirect = overrideManager;
552 viewAttrib.colormap = colorMap;
553
554 foreColor.pixel = foregroundColor;
555 backColor.pixel = backgroundColor;
556 XQueryColor(dsply,colorMap,&foreColor);
557 XQueryColor(dsply,colorMap,&backColor);
558
559 viewAttrib.event_mask = titleMASK;
560 if (vW) {
561 titleSizeHints.flags = PPosition | PSize;
562 titleSizeHints.x = vX;
563 titleSizeHints.y = vY;
564 titleSizeHints.width = vW;
565 titleSizeHints.height = vH;
566 } else {
567 titleSizeHints.flags = PSize;
568 titleSizeHints.width = viewWidth;
569 titleSizeHints.height = viewHeight;
570 }
571
572 viewTitleWindow = XCreateWindow(dsply,rtWindow,vX,vY,vW,vH,
573 viewBorderWidth,
574 CopyFromParent,InputOutput,CopyFromParent,
575 viewportTitleCreateMASK,&viewAttrib);
576
577 wm_delete_window = XInternAtom(dsply, "WM_DELETE_WINDOW", False);
578 (void) XSetWMProtocols(dsply, viewTitleWindow, &wm_delete_window, 1);
579
580 XSetNormalHints(dsply,viewTitleWindow,&titleSizeHints);
581 XSetStandardProperties(dsply,viewTitleWindow,"FriCAS 2D",viewport->title,
582 None,NULL,0,&titleSizeHints);
583
584 viewport->titleWindow = viewTitleWindow;
585 viewAttrib.event_mask = viewportMASK;
586 viewSizeHints.flags = PPosition | PSize;
587 viewSizeHints.x = -viewBorderWidth;
588 viewSizeHints.y = titleHeight;
589 viewSizeHints.width = titleSizeHints.width;
590 viewSizeHints.height = titleSizeHints.height -
591 (titleHeight + appendixHeight);
592 viewGraphWindow = XCreateWindow(dsply,viewTitleWindow,
593 viewSizeHints.x,viewSizeHints.y,
594 viewSizeHints.width,viewSizeHints.height,
595 viewBorderWidth,
596 CopyFromParent,InputOutput,CopyFromParent,
597 viewportCreateMASK,&viewAttrib);
598 XSetNormalHints(dsply,viewGraphWindow,&viewSizeHints);
599 XSetStandardProperties(dsply,viewGraphWindow,"2D Viewport","2D Viewport",
600 None,NULL,0,&viewSizeHints);
601
602 viewport->viewWindow = viewGraphWindow;
603
604 /*Make the control panel for the viewport. */
605 viewport->controlPanel = makeControlPanel();
606 if ((viewport->haveControl = showCP)) putControlPanelSomewhere(anywhere);
607
608 XSync(dsply,False);
609 return(viewport);
610
611 }
612
613
614 /*********************************************
615 ***** viewPoints *makeView2D(viewdata) ****
616 *********************************************/
617
618
619 viewPoints *
makeView2D(view2DStruct * viewdata)620 makeView2D(view2DStruct *viewdata)
621 {
622 viewPoints *vPoints;
623
624 vPoints = makeViewport(viewdata->title, viewdata->vX,viewdata->vY,
625 viewdata->vW,viewdata->vH,viewdata->showCP);
626
627 vPoints->allowDraw = yes; /* draw everything from now on */
628
629 if (viewdata->showCP) clearControlMessage();
630
631 writeTitle();
632
633 XMapWindow(dsply,vPoints->viewWindow);
634 XMapWindow(dsply,vPoints->titleWindow);
635 XSync(dsply,0);
636
637 drawViewport(Xoption); /* draw viewport with X routines (as opposed to PS) */
638 return(vPoints);
639
640 } /* makeView2D */
641