/********** Copyright 1990 Regents of the University of California. All rights reserved. **********/ #include "ngspice/ngspice.h" #include "ngspice/graph.h" #include "ngspice/ftedev.h" #include "ngspice/fteinput.h" #include "ngspice/cpdefs.h" #include "ngspice/ftedefs.h" #ifdef TCL_MODULE #include "ngspice/tclspice.h" #endif #include "display.h" #include "variable.h" static void gen_DatatoScreen(GRAPH *graph, double x, double y, int *screenx, int *screeny); static int gen_Input(REQUEST *request, RESPONSE *response); static int nop(void); #define NOP ((void *)nop) static int nodev(void); #define NODEV ((void *)nodev) #ifndef X_DISPLAY_MISSING #include "plotting/x11.h" #endif #ifdef HAS_WINGUI /* Graphic-IO under MS Windows */ #include "wdisp/windisp.h" //#include "wdisp/winprint.h" #endif #include "plotting/plot5.h" #include "postsc.h" #include "hpgl.h" #include "svg.h" DISPDEVICE device[] = { { "error", 0, 0, 0, 0, 0, 0, (disp_fn_Init_t *) NOP, (disp_fn_NewViewport_t *) NOP, (disp_fn_Close_t *) NOP, (disp_fn_Clear_t *) NOP, (disp_fn_DrawLine_t *) NOP, (disp_fn_Arc_t *) NOP, (disp_fn_Text_t *) NOP, (disp_fn_DefineColor_t *) NOP, (disp_fn_DefineLinestyle_t *) NOP, (disp_fn_SetLinestyle_t *) NOP, (disp_fn_SetColor_t *) NOP, (disp_fn_Update_t *) NOP, (disp_fn_Finalize_t *) NOP, (disp_fn_Track_t *) NOP, (disp_fn_MakeMenu_t *) NOP, (disp_fn_MakeDialog_t *) NOP, gen_Input, (disp_fn_DatatoScreen_t *) NOP,}, #ifndef X_DISPLAY_MISSING { "X11", 0, 0, 1024, 864, 0, 0, X11_Init, X11_NewViewport, X11_Close, X11_Clear, X11_DrawLine, X11_Arc, X11_Text, X11_DefineColor, X11_DefineLinestyle, X11_SetLinestyle, X11_SetColor, X11_Update, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, X11_Input, gen_DatatoScreen,}, #endif #ifdef HAS_WINGUI /* Graphic-IO under MS Windows */ { "Windows", 0, 0, 1000, 1000, 0, 0, WIN_Init, WIN_NewViewport, WIN_Close, WIN_Clear, WIN_DrawLine, WIN_Arc, WIN_Text, WIN_DefineColor, WIN_DefineLinestyle, WIN_SetLinestyle, WIN_SetColor, WIN_Update, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, gen_Input, gen_DatatoScreen, }, /* WIN_DiagramReady */ /* Warning: name "WinPrint" do not change! */ { "WinPrint", 0, 0, 1000, 1000, 0, 0, WPRINT_Init, WPRINT_NewViewport, WPRINT_Close, WPRINT_Clear, WPRINT_DrawLine, WPRINT_Arc, WPRINT_Text, WPRINT_DefineColor, WPRINT_DefineLinestyle, WPRINT_SetLinestyle, WPRINT_SetColor, WPRINT_Update, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, (disp_fn_Input_t *) NODEV, gen_DatatoScreen, }, /* WPRINT_DiagramReady */ #endif #ifdef TCL_MODULE { "Tk", 0, 0, 1024, 864, 0, 0, sp_Tk_Init, sp_Tk_NewViewport, sp_Tk_Close, sp_Tk_Clear, sp_Tk_DrawLine, sp_Tk_Arc, sp_Tk_Text, sp_Tk_DefineColor, sp_Tk_DefineLinestyle, sp_Tk_SetLinestyle, sp_Tk_SetColor, sp_Tk_Update, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, (disp_fn_Input_t *) NODEV, gen_DatatoScreen, }, #endif { "plot5", 0, 0, 1000, 1000, 0, 0, Plt5_Init, Plt5_NewViewport, Plt5_Close, Plt5_Clear, Plt5_DrawLine, Plt5_Arc, Plt5_Text, (disp_fn_DefineColor_t *) NODEV, (disp_fn_DefineLinestyle_t *) NODEV, Plt5_SetLinestyle, Plt5_SetColor, Plt5_Update, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, (disp_fn_Input_t *) NODEV, gen_DatatoScreen, }, { "postscript", 0, 0, 1000, 1000, 0, 0, PS_Init, PS_NewViewport, PS_Close, PS_Clear, PS_DrawLine, PS_Arc, PS_Text, (disp_fn_DefineColor_t *) NODEV, (disp_fn_DefineLinestyle_t *) NODEV, PS_SetLinestyle, PS_SetColor, PS_Update, PS_Finalize, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, (disp_fn_Input_t *) NODEV, gen_DatatoScreen, }, { "svg", 0, 0, 1000, 1000, 0, 0, SVG_Init, SVG_NewViewport, SVG_Close, SVG_Clear, SVG_DrawLine, SVG_Arc, SVG_Text, (disp_fn_DefineColor_t*)NODEV, (disp_fn_DefineLinestyle_t*)NODEV, SVG_SetLinestyle, SVG_SetColor, SVG_Update, SVG_Finalize, (disp_fn_Track_t*)NODEV, (disp_fn_MakeMenu_t*)NODEV, (disp_fn_MakeDialog_t*)NODEV, (disp_fn_Input_t*)NODEV, gen_DatatoScreen, }, { "hpgl", 0, 0, 1000, 1000, 0, 0, GL_Init, GL_NewViewport, GL_Close, GL_Clear, GL_DrawLine, GL_Arc, GL_Text, (disp_fn_DefineColor_t *) NODEV, (disp_fn_DefineLinestyle_t *) NODEV, GL_SetLinestyle, GL_SetColor, GL_Update, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, (disp_fn_Input_t *) NODEV, gen_DatatoScreen, }, { "PrinterOnly", 0, 0, 24, 80, 0, 0, (disp_fn_Init_t *) NODEV, (disp_fn_NewViewport_t *) NODEV, (disp_fn_Close_t *) NOP, (disp_fn_Clear_t *) NODEV, (disp_fn_DrawLine_t *) NODEV, (disp_fn_Arc_t *) NODEV, (disp_fn_Text_t *) NODEV, (disp_fn_DefineColor_t *) NODEV, (disp_fn_DefineLinestyle_t *) NODEV, (disp_fn_SetLinestyle_t *) NODEV, (disp_fn_SetColor_t *) NODEV, (disp_fn_Update_t *) NOP, (disp_fn_Finalize_t*) NOP, (disp_fn_Track_t *) NODEV, (disp_fn_MakeMenu_t *) NODEV, (disp_fn_MakeDialog_t *) NODEV, gen_Input, (disp_fn_DatatoScreen_t *) NODEV, }, }; DISPDEVICE *dispdev = device + NUMELEMS(device) - 1; DISPDEVICE * FindDev(char *name) { size_t i; for (i = 0; i < NUMELEMS(device); i++) if (strcmp(name, device[i].name) == 0) return (device + i); sprintf(ErrorMessage, "Can't find device %s.", name); internalerror(ErrorMessage); return (device + 0); } void DevInit(void) { #ifndef X_DISPLAY_MISSING char buf[128]; #endif /* note: do better determination */ /* dumb tradition that got passed on from gi_interface to do compile time determination */ dispdev = NULL; #ifndef X_DISPLAY_MISSING /* determine display type */ if (getenv("DISPLAY") || cp_getvar("display", CP_STRING, buf, sizeof(buf))) dispdev = FindDev("X11"); #endif #ifdef HAS_WINGUI if (!dispdev) dispdev = FindDev("Windows"); #endif #ifdef TCL_MODULE dispdev = FindDev("Tk"); #endif if (!dispdev) { #if !defined(HAS_WINGUI) && !defined(TCL_MODULE) && !defined(SHARED_MODULE) && (defined(_MSC_VER) || defined(__MINGW32__)) /* console application under MS Windows */ fprintf (cp_err, "Warning: no graphics interface!\n" " You may use command 'gnuplot'\n" " if GnuPlot is installed.\n"); #elif !defined(X_DISPLAY_MISSING) externalerror ("no graphics interface;\n" " please check if X-server is running,\n" " or ngspice is compiled properly (see INSTALL)"); #endif dispdev = FindDev("error"); } else if (dispdev->Init()) { fprintf(cp_err, "Warning: can't initialize display device for graphics.\n"); dispdev = FindDev("error"); } } /* NewViewport is responsible for filling in graph->viewport */ int NewViewport(GRAPH *pgraph) { return dispdev->NewViewport (pgraph); } void DevClose(void) { dispdev->Close(); } void DevClear(void) { dispdev->Clear(); } void DevDrawLine(int x1, int y1, int x2, int y2, bool isgrid) { dispdev->DrawLine (x1, y1, x2, y2, isgrid); } void DevDrawArc(int x0, int y0, int radius, double theta, double delta_theta, bool isgrid) { dispdev->DrawArc (x0, y0, radius, theta, delta_theta, isgrid); } void DevDrawText(const char *text, int x, int y, int angle) { dispdev->DrawText(text, x, y, angle); } void DefineColor(int colorid, double red, double green, double blue) { dispdev->DefineColor (colorid, red, green, blue); } void DefineLinestyle(int linestyleid, int mask) { dispdev->DefineLinestyle (linestyleid, mask); } void SetLinestyle(int linestyleid) { dispdev->SetLinestyle (linestyleid); } void SetColor(int colorid) { dispdev->SetColor(colorid); } void DevUpdate(void) { if (dispdev) dispdev->Update(); } void DevFinalize(void) { if (dispdev) dispdev->Finalize(); } /* note: screen coordinates are relative to window so need to add viewport offsets */ static void gen_DatatoScreen(GRAPH *graph, double x, double y, int *screenx, int *screeny) { double low, high; /* note: may want to cache datawindowsize/viewportsize */ /* done */ /* note: think this out---Is 1 part of the viewport? Do we handle this correctly? */ /* have to handle several types of grids */ /* note: we can't compensate for X's demented y-coordinate system here since the grid routines use DevDrawLine w/o calling this routine */ if ((graph->grid.gridtype == GRID_LOGLOG) || (graph->grid.gridtype == GRID_YLOG)) { low = mylog10(graph->datawindow.ymin); high = mylog10(graph->datawindow.ymax); *screeny = (int)((mylog10(y) - low) / (high - low) * graph->viewport.height + 0.5 + graph->viewportyoff); } else { *screeny = (int)(((y - graph->datawindow.ymin) / graph->aspectratioy) + 0.5 + graph->viewportyoff); } if ((graph->grid.gridtype == GRID_LOGLOG) || (graph->grid.gridtype == GRID_XLOG)) { low = mylog10(graph->datawindow.xmin); high = mylog10(graph->datawindow.xmax); *screenx = (int)((mylog10(x) - low) / (high - low) * graph->viewport.width + 0.5 + graph ->viewportxoff); } else { *screenx = (int)((x - graph->datawindow.xmin) / graph->aspectratiox + 0.5 + graph ->viewportxoff); } } void DatatoScreen(GRAPH *graph, double x, double y, int *screenx, int *screeny) { dispdev->DatatoScreen (graph, x, y, screenx, screeny); } void Input(REQUEST *request, RESPONSE *response) { dispdev->Input (request, response); } static int gen_Input(REQUEST *request, RESPONSE *response) { switch (request->option) { case char_option: if (response) response->option = request->option; break; default: /* just ignore, since we don't want a million error messages */ if (response) response->option = error_option; break; } return (0); } /* no operation, do nothing */ static int nop(void) { return (1); /* so NewViewport will fail */ } static int nodev(void) { sprintf(ErrorMessage, "This operation is not defined for display type %s.", dispdev->name); internalerror(ErrorMessage); return (1); } void SaveText(GRAPH *graph, char *text, int x, int y) { struct _keyed *keyed = TMALLOC(struct _keyed, 1); if (!graph->keyed) { graph->keyed = keyed; } else { keyed->next = graph->keyed; graph->keyed = keyed; } keyed->text = TMALLOC(char, strlen(text) + 1); strcpy(keyed->text, text); keyed->x = x; keyed->y = y; keyed->colorindex = graph->currentcolor; } /* if given name of a hardcopy device, finds it and switches devices if given NULL, switches back */ int DevSwitch(char *devname) { static DISPDEVICE *lastdev = NULL; if (devname) { if (lastdev) { internalerror("DevSwitch w/o changing back"); return (1); } lastdev = dispdev; dispdev = FindDev(devname); if (!strcmp(dispdev->name, "error")) { internalerror("no hardcopy device"); /* undo */ dispdev = lastdev; lastdev = NULL; return (1); } dispdev->Init(); } else { if (dispdev) dispdev->Close(); dispdev = lastdev; lastdev = NULL; } return (0); }