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