📄 x11.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1988 Jeffrey M. Hsu**********//* X11 drivers.*/#include "spice.h"#ifdef HAS_X11# include <sys/time.h># include "util.h"# include "ftegraph.h"# include "ftedbgra.h"# include "ftedev.h"# include "fteinput.h"# include "cpdefs.h"# include "ftedefs.h"# include <IntrinsicP.h># include <Xatom.h># include <StringDefs.h># include <Xutil.h># include <cursorfont.h># include <Box.h># include <Command.h># include <Form.h># include <Shell.h># ifdef DEBUGextern int _Xdebug;# endif/* forward declarations */extern void handlebuttonev(), handlekeypressed(), killwin(), hardcopy(), redraw(), resize();int errorhandler();#define RAD_TO_DEG (180.0 / M_PI)/* X dependent default parameters */#define DEF_FONT "6x10"#define NUMLINESTYLES 8#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 void linear_arc( );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;X11_Init(){ 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] = "spice3"; argv[1] = displayname;/* argv[2] = "-geometry"; argv[3] = "=1x1+2+2";*/ /* initialize X toolkit */ toplevel = XtInitialize("spice3", "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; 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);}interrorhandler(display, errorev)Display *display;XErrorEvent *errorev;{ XGetErrorText(display, errorev->error_code, ErrorMessage, 1024); externalerror(ErrorMessage); return;}/* Recover from bad NewViewPort call. */#define RECOVERNEWVIEWPORT() free((char *) graph);\ graph = (GRAPH *) NULL; /* need to do this or else DestroyGraph will free it again *//* NewViewport is responsible for filling in graph->viewport */X11_NewViewport(graph)GRAPH *graph;{ char geometry[32], defaultgeometry[32]; 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 = calloc(1, 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, handlebuttonev, graph); XtAddEventHandler(DEVDEP(graph).view, KeyPressMask, FALSE, handlekeypressed, graph); XtAddEventHandler(DEVDEP(graph).view, StructureNotifyMask, FALSE, resize, graph); XtAddEventHandler(DEVDEP(graph).view, ExposureMask, FALSE, 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, 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, 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 = 1; 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);}staticinitlinestyles(){ int i; if (numdispplanes > 1) { /* Dotted lines are a distraction when we have colors. */ for (i = 2; i < NUMLINESTYLES; i++) { xlinestyles[i] = xlinestyles[0]; } } return;}staticinitcolors(graph) GRAPH *graph;{ int i; static char *colornames[] = { "white", /* white */ "black", "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; if (i > 0 && graph->colors[i] == DEVDEP(graph).view->core.background_pixel) { graph->colors[i] = 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]; } return;}/* This routine closes the X connection. It is not to be called for finishing a graph. */X11_Close(){ XCloseDisplay(display);}X11_DrawLine(x1, y1, x2, y2)int x1, y1, x2, y2;{ if (DEVDEP(currentgraph).isopen) XDrawLine(display, DEVDEP(currentgraph).window, DEVDEP(currentgraph).gc, x1, currentgraph->absolute.height - y1, x2, currentgraph->absolute.height - y2);}/*ARGSUSED*/X11_Arc(x0, y0, radius, theta1, theta2)int x0, y0, radius;double theta1, 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; XDrawArc(display, DEVDEP(currentgraph).window, DEVDEP(currentgraph).gc, x0 - radius, currentgraph->absolute.height - radius - y0, 2 * radius, 2 * radius, t1, t2);# ifdef notdef printf("at %d, %d, %g %g x %d :: (%d, %d)\n", x0, y0, theta1, theta2, radius, t1, t2); printf("skip\n"); XSync(display, 0); printf("XDrawArc(%d, %d, %d, %d, %d, %d)\n", x0 - radius, currentgraph->absolute.height - radius - y0, 2 * radius, 2 * radius, t1, t2);# endif }}/* note: x and y are the LOWER left corner of text */X11_Text(text, x, y)char *text;int x, 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 - (y + DEVDEP(currentgraph).font->max_bounds.descent), text, strlen(text)); /* note: unlike before, we do not save any text here */}/*ARGSUSED*/X11_DefineColor(colorid, red, green, blue)int colorid;double red, green, blue;{ internalerror("X11_DefineColor not implemented."); return(0);}/*ARGSUSED*/X11_DefineLinestyle(linestyleid, mask)int linestyleid;int mask;{ internalerror("X11_DefineLinestyle not implemented.");}X11_SetLinestyle(linestyleid)int linestyleid;{ XGCValues values; if (currentgraph->linestyle != linestyleid) {# ifdef notdef switch (linestyleid %3) { case 0: values.line_style = LineSolid; break; case 1: values.line_style = LineOnOffDash; break; case 2: values.line_style = LineDoubleDash; break; }# endif if (linestyleid == 0 || numdispplanes > 1 && linestyleid != 1) { /* solid if linestyle 0 or if has color, allow only one * dashed linestyle */ values.line_style = LineSolid; } else { values.line_style = LineOnOffDash; } XChangeGC(display, DEVDEP(currentgraph).gc, GCLineStyle, &values); currentgraph->linestyle = linestyleid; XSetDashes(display, DEVDEP(currentgraph).gc, 0, xlinestyles[linestyleid], 4); }}X11_SetColor(colorid)int colorid;{ currentgraph->currentcolor = colorid; XSetForeground(display, DEVDEP(currentgraph).gc, currentgraph->colors[colorid]);}X11_Update(){ if (X11_Open) XSync(display, 0);}X11_Clear(){ if (!noclear) /* hack so exposures look like they're handled nicely */ XClearWindow(display, DEVDEP(currentgraph).window);}voidhandlekeypressed(w, clientdata, calldata)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -