📄 hgraf.c
字号:
/* calculate width and height */ rw = abs(x1 - x0); rh = abs(y1 - y0); /* the angles are signed integers in 64ths of a degree */ stAngle *=64; arcAngle*=64; XFillArc(theDisp, theWindow, theGC, x0, y0, rw, rh, stAngle, arcAngle);}/* EXPORT-> HPrintf: works as printf on the graphics window at (x,y) */void HPrintf(int x, int y, char *format, ...){ va_list arg; char s[256]; va_start(arg, format); vsprintf(s, format, arg); XDrawString(theDisp, theWindow, theGC, x, y, s, strlen(s));}/* EXPORT-> copy rectangular area of the drawable */void HCopyArea(int srcx, int srcy, int width, int height, int destx, int desty){ XCopyArea(theDisp, theWindow, theWindow, theGC, srcx, srcy, width, height, destx, desty);}/* EXPORT-> HPlotVector: plot vector v in given rectangle */void HPlotVector(int x0, int y0, int x1, int y1, Vector v, int st, int en, float ymax, float ymin){ float yScale, yOffset, xInc, x; int xOld, yOld, ix, iy, i; if (st >= en || st < 1 || en > VectorSize(v)) HError(6815, "HPlotVector: Plot indices %d -> %d out of range", st, en); x = (x1 - x0 - 1); xInc = x/(en - st); yScale = (y1 - y0)/(ymin - ymax); yOffset = y0 - ymax*yScale; x = x0; xOld = (int) x; yOld = (int) (v[st]*yScale + yOffset); for (i = st+1; i <= en; i++){ x += xInc; ix = (int) x; iy = (int) (v[i]*yScale + yOffset); XDrawLine(theDisp, theWindow, theGC, xOld, yOld, ix, iy); xOld = ix; yOld = iy; } }/* ----------------------------- Settings --------------------------------- *//* EXPORT-> HSetFontSize: Set font size in points, 0 selects the default font */void HSetFontSize(int size){ int i, bestf, d, min_d; XferMode xf; if (size==0) CurrentFont = DefaultFont; else { min_d = INT_MAX; bestf = 0; for (i=0; i < FONTS_AVAILABLE; i++) { d=abs(FontSize[i] - size); if (d < min_d) { min_d = d; bestf = i; } } CurrentFont = FontInfo[bestf]; } for (xf = GCOPY; xf <= GINVERT; xf=(XferMode) (xf+1)) /* change all GCs */ XSetFont(theDisp, gcs[(int) xf], CurrentFont->fid); }/* EXPORT-> HSetLineWidth: set the line width */void HSetLineWidth(int w){ XferMode xf; for (xf = GCOPY; xf <= GINVERT; xf=(XferMode) (xf+1)) /* change all GCs */ XSetLineAttributes(theDisp,gcs[(int)xf],w,LineSolid,JoinRound,FillSolid);}/* EXPORT-> HSetXMode: Set current transfer mode */void HSetXMode(XferMode m){ theGC = gcs[(int) m];}/* EXPORT-> CentreX: return position at which the the h-center of str will be at x */int CentreX(int x, char *str){ return (x - XTextWidth(CurrentFont, str, strlen(str))/2);}/* EXPORT-> CentreY: return position at which the the v-center of str will be at y */int CentreY(int y, char *str){ return (y - ((CurrentFont->ascent + CurrentFont->descent)/2) + CurrentFont->ascent);}/* EXPORT HTextWidth: return the width of s in pixels */int HTextWidth(char *str){ return XTextWidth(CurrentFont, str, strlen(str));}/* EXPORT HTextHeight: return the height of s in pixels */int HTextHeight(char *str){ return CurrentFont->ascent + CurrentFont->descent;}/* --------------------------- Misc Routines -----------------------------*//* EXPORT->HDrawImage: draw grey scale image stored in p */void HDrawImage(unsigned char *p, int x, int y, int width, int height){ static XImage *xi = NULL; static unsigned char *mem = NULL; unsigned char *pix; int i, j; if (mem != p){ if (xi != NULL) XDestroyImage(xi); xi = XGetImage(theDisp,theWindow,x,y,width,height,AllPlanes,XYPixmap); pix = mem = p; for (j = 0; j < height; j++) for (i = 0; i < width; i++) XPutPixel(xi, i, j, greys[(int) (*pix++)]); } XPutImage(theDisp, theWindow, theGC, xi, 0, 0, x, y, width, height);}/* EXPORT->HFlush: flush any pending draw operations */void HFlush(void){ XFlush(theDisp);}/* EXPORT-> HSpoolGraf: start saving an image of window in fname */void HSpoolGraf(char *fname){}/* EXPORT->HDumpGraf: dump a pixel image of current display into fname */void HDumpGraf(char *fname){}/* ------------------ Timer routines ------------------ */#ifdef USE_TIMERstatic Boolean timerDone;static void AlarmOn(void){ timerDone = TRUE;}/* Timer: wait for n milliseconds */static void Timer(int n){ long usec; struct itimerval it; usec = (long) n * 1000; memset(&it, 0, sizeof(it)); if (usec>=1000000L) { /* more than 1 second */ it.it_value.tv_sec = usec / 1000000L; usec %= 1000000L; } it.it_value.tv_usec = usec; timerDone=FALSE; signal(SIGALRM, AlarmOn); setitimer(ITIMER_REAL, &it, NULL); while (1) { sigblock(sigmask(SIGALRM)); if (timerDone) break; sigpause(0); } sigblock(0); signal(SIGALRM, SIG_DFL);}#endif/* ---------------------- Button facility ---------------------- */#define BTN_WAIT 200 /* 200 milliseconds minimum button press */#define BTN_LINE_WIDTH 1 /* the line width for button drawing *//* EXPORT->CreateHButton: create a button object with the specified parameters */HButton *CreateHButton(HButton *btnlst, ButtonId btnid, int x, int y, int w, int h, char *str, HColour fg, HColour bg, void (*action)(void)){ HButton *btn, *btnptr; btn = (HButton *) New(&btnHeap, sizeof(HButton)); /* initialise the fields of the structure */ btn->id = btnid; btn->x = x; btn->y = y; btn->w = w; btn->h = h; btn->str = str; btn->fg = fg; btn->bg = bg; btn->lit = FALSE; btn->active = TRUE; btn->toggle = FALSE; btn->next = NULL; /* append it to the end of the list if the list already exists */ if (btnlst!=NULL){ btnptr = btnlst; while (btnptr->next != NULL) btnptr = btnptr->next; btnptr->next = btn; } btn->action = action; /* return ptr to the newly created button */ return btn;}/* EXPORT->RedrawHButton: readraw a single button object */void RedrawHButton(HButton *btn){ int pad = 2; int x, y, w, h, r, s, pos; HPoint poly[9], shad[4]; char sbuf[256], nullchar = '\0'; x = btn->x; y=btn->y; w=btn->w; h=btn->h; r=3; s=1; /* set up the polygon */ poly[0].x = x; poly[0].y = y+r; poly[1].x = x; poly[1].y = y+h-r; poly[2].x = x+r; poly[2].y = y+h; poly[3].x = x+w-r; poly[3].y = y+h; poly[4].x = x+w; poly[4].y = y+h-r; poly[5].x = x+w; poly[5].y = y+r; poly[6].x = x+w-r; poly[6].y = y; poly[7].x = x+r; poly[7].y = y; poly[8].x = x; poly[8].y = y+r; /* set up the extra lines for the shadow */ shad[0].x = x+r+s; shad[0].y = y+h+s; shad[1].x = x+w-r+s; shad[1].y = y+h+s; shad[2].x = x+w+s; shad[2].y = y+h-r+s; shad[3].x = x+w+s; shad[3].y = y+r+s; if (btn->lit) HSetColour(btn->fg); else HSetColour(btn->bg); HFillPolygon(poly, 9); HSetColour(btn->fg); HDrawLines(poly, 9); HDrawLines(shad, 4); if (btn->active) if (btn->lit) HSetColour(btn->bg); else HSetColour(btn->fg); else HSetGrey(30); strcpy(sbuf, btn->str); pos = strlen(sbuf); while(HTextWidth(sbuf) > (w - 2*pad)) sbuf[--pos]=nullchar; HPrintf(CentreX(x+w/2, sbuf), CentreY(y+h/2, sbuf), "%s", sbuf);}/* EXPORT->RedrawHButtonList: redraw the whole list of buttons */void RedrawHButtonList(HButton *btnlst){ HButton *btnptr; HSetLineWidth(BTN_LINE_WIDTH); for (btnptr=btnlst; btnptr!=NULL; btnptr=btnptr->next) RedrawHButton(btnptr);}/* EXPORT->FindButton: find button given name */HButton *FindButton(HButton *btnlst, ButtonId key){ HButton *btnptr; for (btnptr=btnlst; btnptr!=NULL; btnptr=btnptr->next) if (btnptr->id==key) return btnptr; return NULL;}/* EXPORT->SetActive: set active field in button list */void SetActive(HButton *btnlst, Boolean active){ HButton *btnptr; for (btnptr=btnlst; btnptr!=NULL; btnptr=btnptr->next) btnptr->active = active;}/* EXPORT->CheckButtonList: find within which button the point(x,y) is */HButton *CheckButtonList(HButton *btnlst, int x, int y){ HButton *btn; for (btn=btnlst; btn!=NULL; btn=btn->next) if (IsInRect(x, y, btn->x, btn->y, btn->x + btn->w, btn->y + btn->h) && btn->active) return btn; return NULL;}/* EXPORT->SetButtonLit: show button press */void SetButtonLit(HButton *btn, Boolean lit){ if (btn->lit != lit){ btn->lit = lit; RedrawHButton(btn); }}/* EXPORT->TrackButtons: tracks the buttons until the mouse button is released */ButtonId TrackButtons(HButton *btnlist, HEventRec hev){ HButton *pressed, *released; Boolean done; pressed = CheckButtonList(btnlist, hev.x, hev.y); if (pressed != NULL){ SetButtonLit(pressed, TRUE); done = FALSE;#ifdef USE_TIMER HFlush(); Timer(BTN_WAIT);#endif do { hev = HGetEvent(TRUE, pressed->action); done = (hev.event==HMOUSEUP); } while (!done); released = CheckButtonList(btnlist, hev.x, hev.y); SetButtonLit(pressed, FALSE); if ( pressed == released) return pressed->id; } return 0;}/* ------------------ Initialisation and Termination -----------------------*//* InitGCs: each transfer mode is implemented as a different graphics context in X11 *//* the GINVERT mode inverts only the b/w plane and is implemented using GXxor */static void InitGCs(void){ XferMode xf; XGCValues values; unsigned long mask; mask = GCLineWidth | GCFunction | GCForeground; for (xf = GCOPY; xf < GINVERT; xf=(XferMode) (xf+1)){ values.line_width = 0; values.function = TFuncX11[(int) xf]; values.foreground = black; gcs[(int) xf] = XCreateGC(theDisp, theWindow, mask, &values); } mask = GCLineWidth | GCFunction | GCPlaneMask | GCForeground; values.line_width = 0; values.function = GXxor; values.foreground = ~0; values.plane_mask = black ^ white; gcs[(int) GINVERT] = XCreateGC(theDisp, theWindow, mask, &values);}static void InitGlobals(void){ theScreen = DefaultScreen(theDisp); theCmap = DefaultColormap(theDisp, theScreen); rootW = RootWindow(theDisp, theScreen); theGC = DefaultGC(theDisp, theScreen); theVisual = DefaultVisual(theDisp, theScreen); ncells = DisplayCells(theDisp, theScreen); dispWIDE = DisplayWidth(theDisp, theScreen); dispHIGH = DisplayHeight(theDisp, theScreen); dispDEEP = DisplayPlanes(theDisp, theScreen); white = WhitePixel(theDisp,theScreen); black = BlackPixel(theDisp,theScreen);}/* EXPORT-> MakeXGraf: Connect to the X-server and init globals */void MakeXGraf(char *wname, int x, int y, int w, int h, int bw){ char sbuf[256], *hgraf = "HGraf"; Window window, parent; XSetWindowAttributes setwinattr; unsigned long vmask; if (winCreated) HError(6870, "MakeXGraf: Attempt to recreate the graphics window"); if ((theDisp = XOpenDisplay(NULL)) == NULL) HError(6870, "MakeXGraf: cannot connect to X server %s", XDisplayName(NULL)); InitGlobals(); InstallFonts(); InstallColours(); parent = RootWindow(theDisp, theScreen); window = XCreateSimpleWindow(theDisp, parent, x, y, w, h, bw, black, white ); /* allow for backing up the contents of the window */ vmask = CWBackingStore; setwinattr.backing_store = WhenMapped; XChangeWindowAttributes(theDisp, window, vmask, &setwinattr); /* set the size hints for the window manager */ hints.flags = PPosition | PSize | PMaxSize | PMinSize; hints.y = y; hints.x = x; hints.width = w; hints.height = h; hints.min_width = w; hints.min_height = h; hints.max_width = w; hints.max_height = h; /* compose the name of the window */ strcpy(sbuf, hgraf); strcat(sbuf, ": "); strcat(sbuf, wname); XSetStandardProperties(theDisp, window, sbuf, hgraf, None, NULL, 0, &hints); /* select events to receive */ XSelectInput(theDisp, window, ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionHintMask | PointerMotionMask); XMapWindow(theDisp, theWindow = window); InitGCs(); HSetXMode(GCOPY); HSetFontSize(0); HSetLineWidth(0); HSetColour(BLACK); /* wait for the first expose event - cannot draw before it has arrived */ do XNextEvent(theDisp, &report); while (report.type != Expose); XSendEvent(theDisp,window,False,ExposureMask,&report); /* Create heap for buttons */ CreateHeap(&btnHeap, "Button heap", MHEAP, sizeof(HButton), 1.0, 100, 100); winCreated = TRUE;}/* EXPORT->TermHGraf: Terminate Graphics (also called via at_exit) */void TermHGraf(){ if (theDisp != NULL) XCloseDisplay(theDisp); DeleteHeap(&btnHeap);}/* ------------------------ End of HGraf.X.c ------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -