📄 x11.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1988 Jeffrey M. Hsu$Id: x11.c,v 1.16 2005/08/22 19:29:20 pnenzi Exp $**********//* X11 drivers.*/#include <ngspice.h>#ifndef X_DISPLAY_MISSING# include <sys/time.h># include <sys/types.h> /* PN */# include <unistd.h> /* PN */# include <graph.h># include <ftedbgra.h># include <ftedev.h># include <fteinput.h># include <cpdefs.h># include <ftedefs.h># include <variable.h>/* Added X11/ prefix to the next includes - ER */# include <X11/IntrinsicP.h># include <X11/Xatom.h># include <X11/StringDefs.h># include <X11/Xutil.h># include <X11/cursorfont.h># include <X11/Xaw/Box.h># include <X11/Xaw/Command.h># include <X11/Xaw/Form.h># include <X11/Shell.h># ifdef DEBUG# include <X11/Xlib.h> /* for _Xdebug */# endif#include "x11.h"#include "graphdb.h"#include "display.h"#include "graf.h"#include "../error.h"#define RAD_TO_DEG (180.0 / M_PI)/* X dependent default parameters */#define DEF_FONT "10x14"#define NUMLINESTYLES 8#define MW_LINEWIDTH 2 /* MW. I want larger lines */#define NXPLANES 5 /* note: What is this used for? */#define BOXSIZE 30 /* initial size of bounding box for zoomin */typedef struct x11info { Window window; int isopen; Widget shell, form, view, buttonbox, buttons[2]; XFontStruct *font; GC gc; int lastx, lasty; /* used in X_DrawLine */ int lastlinestyle; /* used in X_DrawLine */} X11devdep;#define DEVDEP(g) (*((X11devdep *) (g)->devdep))static Display *display;static GC xorgc;static char *xlinestyles[NUMLINESTYLES] = { /* test patterns XXX */ "\001\001\001\001", /* solid */ "\001\002\001\002", /* dots */ "\007\007\007\007", /* longdash */ "\003\003\003\003", /* shortdash */ "\007\002\002\002", /* dots longdash */ "\003\002\001\002", /* dots shortdash */ "\003\003\007\003", /* short/longdash */};static Widget toplevel;static Bool noclear = False;static GRAPH *lasthardcopy; /* graph user selected */static int X11_Open = 0;static int numdispplanes;/* static functions */static void initlinestyles (void);static void initcolors (GRAPH *graph);static void X_ScreentoData (GRAPH *graph, int x, int y, double *fx, double *fy);static void linear_arc(int x0, int y0, int radius, double theta1, double theta2);interrorhandler(Display *display, XErrorEvent *errorev){ XGetErrorText(display, errorev->error_code, ErrorMessage, 1024); externalerror(ErrorMessage); return 0;}intX11_Init(void){ char buf[512]; char *displayname; XGCValues gcvalues; /* grrr, Xtk forced contortions */ char *argv[2]; int argc = 2; if (cp_getvar("display", VT_STRING, buf)) { displayname = buf; } else if (!(displayname = getenv("DISPLAY"))) { internalerror("Can't open X display."); return (1); }# ifdef DEBUG _Xdebug = 1;# endif argv[0] = "ngspice"; argv[1] = displayname;/* argv[2] = "-geometry"; argv[3] = "=1x1+2+2";*/ /* initialize X toolkit */ toplevel = XtInitialize("ngspice", "Nutmeg", NULL, 0, &argc, argv); display = XtDisplay(toplevel); X11_Open = 1; /* "invert" works better than "xor" for B&W */ /* xor gc should be a function of the pixels that are written on */ /* gcvalues.function = GXxor; */ /* this patch makes lines visible on true color displays Guenther Roehrich 22-Jan-99 */ gcvalues.function = GXinvert; gcvalues.line_width = 1; gcvalues.foreground = 1; gcvalues.background = 0; xorgc = XCreateGC(display, DefaultRootWindow(display), GCLineWidth | GCFunction | GCForeground | GCBackground, &gcvalues); /* set correct information */ dispdev->numlinestyles = NUMLINESTYLES; dispdev->numcolors = NUMCOLORS; dispdev->width = DisplayWidth(display, DefaultScreen(display)); dispdev->height = DisplayHeight(display, DefaultScreen(display)); /* we don't want non-fatal X errors to call exit */ XSetErrorHandler(errorhandler); numdispplanes = DisplayPlanes(display, DefaultScreen(display)); return (0);}static voidinitlinestyles(void){ int i; if (numdispplanes > 1) { /* Dotted lines are a distraction when we have colors. */ for (i = 2; i < NUMLINESTYLES; i++) { xlinestyles[i] = xlinestyles[0]; } }}static voidinitcolors(GRAPH *graph){ int i; static char *colornames[] = { "black", /* white */ "white", "red", "blue", "orange", "green", "pink", "brown", "khaki", "plum", "orchid", "violet", "maroon", "turquoise", "sienna", "coral", "cyan", "magenta", "gold", "yellow", "" }; XColor visualcolor, exactcolor; char buf[BSIZE_SP], colorstring[BSIZE_SP]; int xmaxcolors = NUMCOLORS; /* note: can we get rid of this? */ if (numdispplanes == 1) { /* black and white */ xmaxcolors = 2; graph->colors[0] = DEVDEP(graph).view->core.background_pixel; if (graph->colors[0] == WhitePixel(display, DefaultScreen(display))) graph->colors[1] = BlackPixel(display, DefaultScreen(display)); else graph->colors[1] = WhitePixel(display, DefaultScreen(display)); } else { if (numdispplanes < NXPLANES) xmaxcolors = 1 << numdispplanes; for (i = 0; i < xmaxcolors; i++) { (void) sprintf(buf, "color%d", i); if (!cp_getvar(buf, VT_STRING, colorstring)) (void) strcpy(colorstring, colornames[i]); if (!XAllocNamedColor(display, DefaultColormap(display, DefaultScreen(display)), colorstring, &visualcolor, &exactcolor)) { (void) sprintf(ErrorMessage, "can't get color %s\n", colorstring); externalerror(ErrorMessage); graph->colors[i] = i ? BlackPixel(display, DefaultScreen(display)) : WhitePixel(display, DefaultScreen(display)); continue; } graph->colors[i] = visualcolor.pixel; /* MW. I don't need this, everyone must know what he is doing if (i > 0 && graph->colors[i] == DEVDEP(graph).view->core.background_pixel) { graph->colors[i] = graph->colors[0]; } */ } /* MW. Set Beackgroound here */ XSetWindowBackground(display, DEVDEP(graph).window, graph->colors[0]); /* if (graph->colors[0] != DEVDEP(graph).view->core.background_pixel) { graph->colors[0] = DEVDEP(graph).view->core.background_pixel; } */ } for (i = xmaxcolors; i < NUMCOLORS; i++) { graph->colors[i] = graph->colors[i + 1 - xmaxcolors]; }}voidhandlekeypressed(Widget w, caddr_t clientdata, caddr_t calldata){ XKeyEvent *keyev = (XKeyPressedEvent *) calldata; GRAPH *graph = (GRAPH *) clientdata; char text[4]; int nbytes; nbytes = XLookupString(keyev, text, 4, NULL, NULL); if (!nbytes) return; /* write it */ PushGraphContext(graph); text[nbytes] = '\0'; SetColor(1); Text(text, keyev->x, graph->absolute.height - keyev->y); /* save it */ SaveText(graph, text, keyev->x, graph->absolute.height - keyev->y); /* warp mouse so user can type in sequence */ XWarpPointer(display, None, DEVDEP(graph).window, 0, 0, 0, 0, keyev->x + XTextWidth(DEVDEP(graph).font, text, nbytes), keyev->y); PopGraphContext();}voidhandlebuttonev(Widget w, caddr_t clientdata, caddr_t calldata){ XButtonEvent *buttonev = (XButtonEvent *) calldata; switch (buttonev->button) { case Button1: slopelocation((GRAPH *) clientdata, buttonev->x, buttonev->y); break; case Button3: zoomin((GRAPH *) clientdata); break; }}/* Recover from bad NewViewPort call. */#define RECOVERNEWVIEWPORT() tfree(graph);\ graph = (GRAPH *) NULL; /* need to do this or else DestroyGraph will free it again *//* NewViewport is responsible for filling in graph->viewport */intX11_NewViewport(GRAPH *graph){ char fontname[513]; /* who knows . . . */ char *p, *q; Cursor cursor; XSetWindowAttributes w_attrs; XGCValues gcvalues; static Arg formargs[ ] = { { XtNleft, (XtArgVal) XtChainLeft }, { XtNresizable, (XtArgVal) TRUE } }; static Arg bboxargs[ ] = { { XtNfromHoriz, (XtArgVal) NULL }, { XtNbottom, (XtArgVal) XtChainTop }, { XtNtop, (XtArgVal) XtChainTop }, { XtNleft, (XtArgVal) XtChainRight }, { XtNright, (XtArgVal) XtChainRight } }; static Arg buttonargs[ ] = { { XtNlabel, (XtArgVal) NULL }, { XtNfromVert, (XtArgVal) NULL }, { XtNbottom, (XtArgVal) XtChainTop }, { XtNtop, (XtArgVal) XtChainTop }, { XtNleft, (XtArgVal) XtRubber }, { XtNright, (XtArgVal) XtRubber }, { XtNresizable, (XtArgVal) TRUE } }; static Arg viewargs[] = { { XtNresizable, (XtArgVal) TRUE }, { XtNwidth, (XtArgVal) 300 }, { XtNheight, (XtArgVal) 300 }, { XtNright, (XtArgVal) XtChainRight } }; int trys; graph->devdep = tmalloc(sizeof(X11devdep)); /* set up new shell */ DEVDEP(graph).shell = XtCreateApplicationShell("shell", topLevelShellWidgetClass, NULL, 0); /* set up form widget */ DEVDEP(graph).form = XtCreateManagedWidget("form", formWidgetClass, DEVDEP(graph).shell, formargs, XtNumber(formargs)); /* set up viewport */ DEVDEP(graph).view = XtCreateManagedWidget("viewport", widgetClass, DEVDEP(graph).form, viewargs, XtNumber(viewargs)); XtAddEventHandler(DEVDEP(graph).view, ButtonPressMask, FALSE, (XtEventHandler) handlebuttonev, graph); XtAddEventHandler(DEVDEP(graph).view, KeyPressMask, FALSE, (XtEventHandler) handlekeypressed, graph); XtAddEventHandler(DEVDEP(graph).view, StructureNotifyMask, FALSE, (XtEventHandler) resize, graph); XtAddEventHandler(DEVDEP(graph).view, ExposureMask, FALSE, (XtEventHandler) redraw, graph); /* set up button box */ XtSetArg(bboxargs[1], XtNfromHoriz, DEVDEP(graph).view); DEVDEP(graph).buttonbox = XtCreateManagedWidget("buttonbox", boxWidgetClass, DEVDEP(graph).form, bboxargs, XtNumber(bboxargs)); /* set up buttons */ XtSetArg(buttonargs[0], XtNlabel, "quit"); XtSetArg(bboxargs[1], XtNfromVert, NULL); DEVDEP(graph).buttons[0] = XtCreateManagedWidget("quit", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 1); XtAddCallback(DEVDEP(graph).buttons[0], XtNcallback, (XtCallbackProc) killwin, graph); XtSetArg(buttonargs[0], XtNlabel, "hardcopy"); XtSetArg(bboxargs[1], XtNfromVert, DEVDEP(graph).buttons[0]); DEVDEP(graph).buttons[1] = XtCreateManagedWidget("hardcopy", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 1); XtAddCallback(DEVDEP(graph).buttons[1], XtNcallback, (XtCallbackProc) hardcopy, graph); /* set up fonts */ if (!cp_getvar("font", VT_STRING, fontname)) { (void) strcpy(fontname, DEF_FONT); } for (p = fontname; *p && *p <= ' '; p++) ; if (p != fontname) { for (q = fontname; *p; *q++ = *p++) ; *q = 0; } trys = 1; while (!(DEVDEP(graph).font = XLoadQueryFont(display, fontname))) { sprintf(ErrorMessage, "can't open font %s", fontname); strcpy(fontname, "fixed"); if (trys > 1) { internalerror(ErrorMessage); RECOVERNEWVIEWPORT(); return(1); } trys += 1; } graph->fontwidth = DEVDEP(graph).font->max_bounds.rbearing - DEVDEP(graph).font->min_bounds.lbearing + 1; graph->fontheight = DEVDEP(graph).font->max_bounds.ascent + DEVDEP(graph).font->max_bounds.descent + 1; XtRealizeWidget(DEVDEP(graph).shell); DEVDEP(graph).window = XtWindow(DEVDEP(graph).view); DEVDEP(graph).isopen = 0; w_attrs.bit_gravity = ForgetGravity; XChangeWindowAttributes(display, DEVDEP(graph).window, CWBitGravity, &w_attrs); /* have to note font and set mask GCFont in XCreateGC, p.w.h. */ gcvalues.font = DEVDEP(graph).font->fid; gcvalues.line_width = MW_LINEWIDTH; gcvalues.cap_style = CapNotLast; gcvalues.function = GXcopy; DEVDEP(graph).gc = XCreateGC(display, DEVDEP(graph).window, GCFont | GCLineWidth | GCCapStyle | GCFunction, &gcvalues); /* should absolute.positions really be shell.pos? */ graph->absolute.xpos = DEVDEP(graph).view->core.x; graph->absolute.ypos = DEVDEP(graph).view->core.y; graph->absolute.width = DEVDEP(graph).view->core.width; graph->absolute.height = DEVDEP(graph).view->core.height; initlinestyles(); initcolors(graph); /* set up cursor */ cursor = XCreateFontCursor(display, XC_left_ptr); XDefineCursor(display, DEVDEP(graph).window, cursor); return (0);}/* This routine closes the X connection. It is not to be called for finishing a graph. */intX11_Close(void){ XCloseDisplay(display); return 0;}intX11_DrawLine(int x1, int y1, int x2, int y2){ if (DEVDEP(currentgraph).isopen) XDrawLine(display, DEVDEP(currentgraph).window, DEVDEP(currentgraph).gc, x1, currentgraph->absolute.height - y1, x2, currentgraph->absolute.height - y2); return 0;}intX11_Arc(int x0, int y0, int radius, double theta1, double theta2){ int t1, t2; if (!cp_getvar("x11lineararcs", VT_BOOL, (char *) &t1)) { linear_arc(x0, y0, radius, theta1, theta2); } if (DEVDEP(currentgraph).isopen) { if (theta1 >= theta2) theta2 = 2 * M_PI + theta2; t1 = 64 * (180.0 / M_PI) * theta1; t2 = 64 * (180.0 / M_PI) * theta2 - t1; if (t2 == 0) return 0; XDrawArc(display, DEVDEP(currentgraph).window, DEVDEP(currentgraph).gc, x0 - radius, currentgraph->absolute.height - radius - y0, 2 * radius, 2 * radius, t1, t2); } return 0;}/* note: x and y are the LOWER left corner of text */intX11_Text(char *text, int x, int y){ /* We specify text position by lower left corner, so have to adjust for X11's font nonsense. */ if (DEVDEP(currentgraph).isopen) XDrawString(display, DEVDEP(currentgraph).window, DEVDEP(currentgraph).gc, x, currentgraph->absolute.height
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -