1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California.  All rights reserved.
4 Authors: 1987 UCB
5          1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include "plotdefs.h"
10 
11 #ifdef __STDC__
12 static int gen_DatatoScreen(GRAPH*,double,double,int*,int*);
13 static int gen_Input(REQUEST*,RESPONSE*);
14 static int nodev();
15 static int nop();
16 #else
17 static int gen_DatatoScreen();
18 static int gen_Input();
19 static int nodev();
20 static int nop();
21 #endif
22 
23 
24 DISPDEVICE device[] = {
25 
26     {"error",
27     false, false, 0, 0, 0, 0, 0, 0, nop, nop,
28     nop, nop, nop, nop,
29     nop, nop, nop, nop,
30     nop, nop, nop,
31     nop, nop, nop,
32     nop, nop,
33     nop, nop, nop, gen_Input,
34     nop,},
35 
36 #ifdef HAVE_X11
37     {"X11",
38     true, false, 0, 0, 1024, 864, 0, 0, X11_Init, X11_NewViewport,
39     X11_Close, X11_Halt, X11_Clear, X11_Title,
40     X11_Pixel, X11_Line, X11_Box, X11_Arc,
41     X11_Polygon, X11_Text, X11_SetGhost,
42     X11_DefineColor, X11_DefineLinestyle, X11_SetLinestyle,
43     X11_SetColor, X11_Update,
44     nodev, nodev, nodev, X11_Input,
45     gen_DatatoScreen,},
46 #endif
47 
48 #ifdef HAVE_MFB
49     {"MFB",
50     false, false, 0, 0, 1000, 1000, 0, 0, Mfb_Init, Mfb_NewViewport,
51     Mfb_Close, Mfb_Halt, Mfb_Clear, nop,
52     Mfb_Pixel, Mfb_Line, Mfb_Box, Mfb_Arc,
53     Mfb_Polygon, Mfb_Text, Mfb_SetGhost,
54     Mfb_DefineColor, Mfb_DefineLinestyle, Mfb_SetLinestyle,
55     Mfb_SetColor, Mfb_Update,
56     nodev, Mfb_MakeMenu, Mfb_MakeDialog, Mfb_Input,
57     gen_DatatoScreen,},
58 #endif
59 
60     {"plot5",
61     false, true, 0, 0, 1000, 1000, 0, 0, Plt5_Init, Plt5_NewViewport,
62     Plt5_Close, Plt5_Halt, nop, nop,
63     Plt5_Pixel, Plt5_Line, Plt5_Box, Plt5_Arc,
64     Plt5_Polygon, Plt5_Text, nop,
65     nop, nop, Plt5_SetLinestyle,
66     Plt5_SetColor, Plt5_Update,
67     nop, nop, nop, nop,
68     gen_DatatoScreen,},
69 
70     {"postscript",
71     false, true, 0, 0, 1000, 1000, 0, 0, PS_Init, PS_NewViewport,
72     PS_Close, PS_Halt, nop, nop,
73     PS_Pixel, PS_Line, PS_Box, PS_Arc,
74     PS_Polygon, PS_Text, nop,
75     nop, nop, PS_SetLinestyle,
76     PS_SetColor, PS_Update,
77     nop, nop, nop, nop,
78     gen_DatatoScreen,},
79 
80     {"laser",
81     false, true, 0, 0, 1000, 1000, 0, 0, HP_Init, HP_NewViewport,
82     HP_Close, HP_Halt, nop, nop,
83     HP_Pixel, HP_Line, HP_Box, HP_Arc,
84     HP_Polygon, HP_Text, nop,
85     nop, HP_DefineLinestyle, HP_SetLinestyle,
86     nop, nop,
87     nop, nop, nop, nop,
88     gen_DatatoScreen,},
89 
90     {"wp",
91     false, true, 0, 0, 1000, 1000, 0, 0, WP_Init, WP_NewViewport,
92     WP_Close, WP_Halt, nop, nop,
93     WP_Pixel, WP_Line, WP_Box, WP_Arc,
94     WP_Polygon, WP_Text, nop,
95     nop, nop, WP_SetLinestyle,
96     nop, nop,
97     nop, nop, nop, nop,
98     gen_DatatoScreen,},
99 
100     {"printf",
101     false, true, 0, 0, 24, 80, 0, 0, nodev, nodev,
102     nodev, nodev, nodev, nodev,
103     nodev, nodev, nodev, nodev,
104     nodev, nodev, nodev,
105     nodev, nodev, nodev,
106     nodev, nodev,
107     nodev, nodev, nodev, nodev,
108     nodev,},
109 
110 };
111 
112 DISPDEVICE *dispdev;
113 
114 #define XtNumber(arr)       (sizeof(arr) / sizeof(arr[0]))
115 
116 
117 DISPDEVICE *
FindDev(name)118 FindDev(name)
119 
120 char *name;
121 {
122     int i;
123 
124     for (i=0; i < XtNumber(device); i++) {
125         if (!strcmp(name, device[i].name)) {
126             return (&device[i]);
127         }
128     }
129     sprintf(ErrorMessage, "Can't find device %s.", name);
130     internalerror(ErrorMessage);
131     return (&device[0]);
132 }
133 
134 int
DevXterm(string)135 DevXterm(string)
136 
137 char *string;
138 {
139     char buf[BSIZE_SP];
140 
141     if (dispdev->windows)
142         (void) sprintf(buf, "xterm -e %s", string);
143     else
144         (void) sprintf(buf, "%s", string);
145 
146     return (system(buf));
147 }
148 
149 
150 void
DevGrHalt()151 DevGrHalt()
152 
153 {
154     int id;
155 
156     /* halt graphics if not windowed */
157     if (!dispdev->windows &&
158             currentgraph && currentgraph->graphtype != GR_SCED) {
159         DevHalt();
160         id = currentgraph->graphid;
161         PopGraphContext();
162         DestroyGraph(id);
163     }
164 }
165 
166 
167 void
DevInit()168 DevInit()
169 
170 {
171     char buf[128];
172     extern char *kw_display;
173 
174 /* note: do better determination */
175 /*
176     dumb tradition that got passed on from gi_interface
177     to do compile time determination
178 */
179 #ifdef HAVE_MFB
180 #ifdef HAVE_X11
181     /* determine display type */
182     if (cp_display)
183         dispdev = FindDev("X11");
184     else
185         dispdev = FindDev("MFB");
186 #else       /* MFB but not X */
187     dispdev = FindDev("MFB");
188 #endif
189 #else
190 #ifdef HAVE_X11
191     dispdev = FindDev("X11");
192 #else       /* no MFB nor X */
193     externalerror(
194     "no graphics packages; need to define either WANT_X11, or WANT_MFB");
195     dispdev = FindDev("error");
196 #endif
197 #endif
198 
199     if ((*(dispdev->Init))()) {
200         fprintf(cp_err,
201         "Warning: can't initialize display device for graphics.\n");
202         dispdev = FindDev("error");
203     }
204 }
205 
206 
207 /* NewViewport is responsible for filling in graph->viewport */
208 int
DevNewViewport(pgraph)209 DevNewViewport(pgraph)
210 
211 GRAPH *pgraph;
212 {
213     return (*(dispdev->NewViewport))(pgraph);
214 }
215 
216 
217 void
DevClose()218 DevClose()
219 
220 {
221     (void)(*(dispdev->Close))();
222 }
223 
224 
225 void
DevHalt()226 DevHalt()
227 
228 {
229     (void)(*(dispdev->Halt))();
230 }
231 
232 
233 void
DevClear()234 DevClear()
235 
236 {
237     (void)(*(dispdev->Clear))();
238 }
239 
240 
241 void
DevTitle(wintitle,icontitle)242 DevTitle(wintitle,icontitle)
243 
244 char *wintitle, *icontitle;
245 {
246     (void)(*(dispdev->Title))(wintitle,icontitle);
247 }
248 
249 
250 void
DevPixel(x,y)251 DevPixel(x, y)
252 
253 int x, y;
254 {
255     (void)(*(dispdev->Pixel))(x, y);
256 }
257 
258 
259 void
DevLine(x1,y1,x2,y2)260 DevLine(x1, y1, x2, y2)
261 
262 int x1, y1, x2, y2;
263 {
264     (void)(*(dispdev->Line))(x1, y1, x2, y2);
265 }
266 
267 
268 void
DevBox(x1,y1,x2,y2)269 DevBox(x1, y1, x2, y2)
270 
271 int x1, y1, x2, y2;
272 {
273     (void)(*(dispdev->Box))(x1, y1, x2, y2);
274 }
275 
276 
277 void
DevArc(x0,y0,radius,theta1,theta2)278 DevArc(x0, y0, radius, theta1, theta2)
279 
280 int x0, y0, radius;
281 double theta1, theta2;
282 {
283     (void)(*(dispdev->Arc))(x0, y0, radius, theta1, theta2);
284 }
285 
286 
287 void
DevPolygon(p)288 DevPolygon(p)
289 
290 POLYGON *p;
291 {
292     (void)(*(dispdev->Polygon))(p);
293 }
294 
295 
296 void
DevText(text,x,y)297 DevText(text, x, y)
298 
299 char *text;
300 int x, y;
301 {
302     (void)(*(dispdev->Text))(text, x, y);
303 }
304 
305 
306 void
307 DevSetGhost(callback,x,y)
308 
309 #ifdef __STDC__
310 void (*callback)(int,int,int,int);
311 #else
312 void (*callback)();
313 #endif
314 int x,y;
315 {
316     (void)(*(dispdev->SetGhost))(callback, x, y);
317 }
318 
319 
320 void
DevDefineColor(colorid,red,green,blue)321 DevDefineColor(colorid, red, green, blue)
322 
323 int colorid;
324 double red, green, blue;
325 {
326     (void)(*(dispdev->DefineColor))(colorid, red, green, blue);
327 }
328 
329 
330 void
DevDefineLinestyle(linestyleid,mask)331 DevDefineLinestyle(linestyleid, mask)
332 
333 int linestyleid;
334 int mask;
335 {
336     (void)(*(dispdev->DefineLinestyle))(linestyleid, mask);
337 }
338 
339 
340 void
DevSetLinestyle(linestyleid)341 DevSetLinestyle(linestyleid)
342 
343 int linestyleid;
344 {
345     (void)(*(dispdev->SetLinestyle))(linestyleid);
346 }
347 
348 
349 void
DevSetColor(colorid)350 DevSetColor(colorid)
351 
352 int colorid;
353 {
354     (void)(*(dispdev->SetColor))(colorid);
355 }
356 
357 
358 void
DevUpdate()359 DevUpdate()
360 {
361     (void)(*(dispdev->Update))();
362 }
363 
364 
365 /* note: screen coordinates are relative to window
366  * so need to add viewport offsets
367  */
368 static int
gen_DatatoScreen(graph,x,y,screenx,screeny)369 gen_DatatoScreen(graph, x, y, screenx, screeny)
370 
371 GRAPH *graph;
372 double x, y;
373 int *screenx, *screeny;
374 {
375     double low, high;
376 
377     /* note: think this out---Is 1 part of the viewport? Do we handle
378         this correctly? */
379 
380     /* have to handle several types of grids */
381 
382     /* note: we can't compensate for X's demented y-coordinate system here
383         since the grid routines use DevLine w/o calling this routine */
384     if ((graph->grid.gridtype == GRID_LOGLOG) ||
385             (graph->grid.gridtype == GRID_YLOG)) {
386         low = mylog10(graph->datawindow.ymin);
387         high = mylog10(graph->datawindow.ymax);
388         *screeny = rnd( (((mylog10(y) - low) / (high - low))
389             * graph->viewport.height)
390             + graph->viewportyoff );
391     }
392     else {
393         *screeny = rnd( ((y - graph->datawindow.ymin) / graph->aspectratioy)
394             + graph->viewportyoff );
395     }
396 
397     if ((graph->grid.gridtype == GRID_LOGLOG) ||
398             (graph->grid.gridtype == GRID_XLOG)) {
399         low = mylog10(graph->datawindow.xmin);
400         high = mylog10(graph->datawindow.xmax);
401         *screenx = rnd( ((mylog10(x) - low) / (high - low))
402             * graph->viewport.width
403             + graph ->viewportxoff);
404     }
405     else {
406         *screenx = rnd( (x - graph->datawindow.xmin) / graph->aspectratiox
407             + graph ->viewportxoff);
408     }
409     return (0);
410 }
411 
412 
413 void
DevDatatoScreen(graph,x,y,screenx,screeny)414 DevDatatoScreen(graph, x, y, screenx, screeny)
415 
416 GRAPH *graph;
417 double x, y;
418 int *screenx, *screeny;
419 {
420     (void)(*(dispdev->DatatoScreen))(graph, x, y, screenx, screeny);
421 }
422 
423 #ifdef notdef
424 /*
425 void
426 NDCtoScreen(x0, y0, px, py)
427 
428 double x0, y0;
429 int *px, *py;
430 {
431     (void)(*(dispdev->NDCtoScreen))(x0, y0, px, py);
432 }
433 */
434 #endif
435 
436 
437 void
DevInput(request,response)438 DevInput(request, response)
439 
440 REQUEST *request;
441 RESPONSE *response;
442 {
443     (void)(*(dispdev->Input))(request, response);
444 }
445 
446 
447 static int
gen_Input(request,response)448 gen_Input(request, response)
449 
450 REQUEST *request;
451 RESPONSE *response;
452 {
453     switch (request->option) {
454         case char_option:
455             response->reply.ch = cp_inchar(request->fp);
456             response->option = request->option;
457             break;
458         default:
459             /* just ignore, since we don't want a million error messages */
460             if (response)
461                 response->option = error_option;
462             break;
463     }
464     return (0);
465 }
466 
467 
468 /* no operation, do nothing */
nop()469 static int nop()
470 {
471     return (1);  /* so NewViewport will fail */
472 }
473 
474 
475 static int
nodev()476 nodev()
477 {
478     sprintf(ErrorMessage,
479         "This operation is not defined for display type %s.",
480         dispdev->name);
481     internalerror(ErrorMessage);
482     return (1);
483 }
484 
485 
486 void
SaveText(graph,text,x,y)487 SaveText(graph, text, x, y)
488 
489 GRAPH *graph;
490 char *text;
491 int x, y;
492 {
493     struct _keyed *keyed;
494 
495     keyed = (struct _keyed *) calloc(1, sizeof(struct _keyed));
496 
497     if (!graph->keyed) {
498        graph->keyed = keyed;
499     }
500     else {
501        keyed->next = graph->keyed;
502        graph->keyed = keyed;
503     }
504 
505     keyed->text = tmalloc(strlen(text) + 1);
506     strcpy(keyed->text, text);
507 
508     keyed->x = x;
509     keyed->y = y;
510 
511     keyed->colorindex = 1;
512 }
513 
514 
515 int
DevSwitch(devname)516 DevSwitch(devname)
517 
518 /* if given name of a hardcopy device, finds it and switches devices
519  * if given NULL, switches back
520  */
521 char *devname;
522 {
523     static DISPDEVICE *lastdev = NULL;
524 
525     if (devname != NULL) {
526         if (lastdev != NULL) {
527             internalerror("DevSwitch w/o changing back");
528             return (1);
529         }
530         lastdev = dispdev;
531         dispdev = FindDev(devname);
532         if (!strcmp(dispdev->name, "error")) {
533             internalerror("no hardcopy device");
534             dispdev = lastdev;  /* undo */
535             lastdev = NULL;
536             return (1);
537         }
538         (*(dispdev->Init))();
539     }
540     else {
541         (*(dispdev->Close))();
542         dispdev = lastdev;
543         lastdev = NULL;
544     }
545     return (0);
546 }
547 
548 
549 int
DevGetchar(fp)550 DevGetchar(fp)
551 
552 FILE *fp;
553 {
554     REQUEST request;
555     RESPONSE response;
556 
557     request.option = char_option;
558     request.fp = fp;
559     DevInput(&request, &response);
560     return(response.reply.ch);
561 }
562