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