📄 graphic.c
字号:
/* YABASIC --- a simple Basic Interpreter written by Marc-Oliver Ihm 1995-2004 homepage: www.yabasic.de graphic.c --- code for windowed graphics, printing and plotting This file is part of yabasic and may be copied only under the terms of either the Artistic License or the GNU General Public License (GPL), both of which can be found at www.yabasic.de*//* ------------- defines ---------------- */#ifdef WINDOWS#define WM_WANTKEY (WM_APP+7)#endif/* ------------- includes ---------------- */#ifndef YABASIC_INCLUDED#include "yabasic.h" /* all prototypes and structures */#endif#ifdef UNIX#include <curses.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#ifndef KEY_MAX#define KEY_MAX 0777#endif#endif/* ------------- local functions ---------------- */static void transform(double *,double *); /* do transformation */static void itransform(int *,int *); /* integer variant of transform() */static int grafinit(void); /* initialize grafics (either X or Windows) */static void addbits(char *,int); /* add one bit to bitstring */static char *newbits(int,int); /* create a new bitmap string */static int readbits(char *); /* read bits from string one after another */#ifdef WINDOWSstatic DWORD winthread(LPWORD); /* window thread */static void startdraw(int); /* prepare for drawing */#endif/* ------------- global variables ---------------- *//* printing and plotting */static char *printerfilename=NULL; /* filename to print on */static int deleteprinterfile=FALSE; /* true, if we created the filename ourself an can delete it on close */int print_to_file=FALSE; /* print to file ? */#ifdef WINDOWSHFONT printerfont; /* handle of printer-font */static HPEN printerpen; /* handle of printer-pen */static HPEN revprinterpen; /* handle of reverse printer-pen */HDC printer=NULL; /* handle of printer */static float prnscale; /* scaling factor for printer */static float prnoffx; /* offset for printer */static float prnoffy; /* offset for printer */#elseFILE *printerfile=NULL; /* file to print on */static double psscale; /* factor from window-pixels to ps-points */static int firsttext=TRUE; /* true until text has been printed */#endifint drawmode=0; /* flag for drawing *//* window coordinates */int winopened=FALSE; /* flag if window is open already */char *winorigin; /* e.g. "lt","rc"; defines origin of grafic window */int winwidth,winheight; /* size of window */static int winx,winy; /* position of window *//* mouse and keyboard */int mousex=0,mousey=0,mouseb=0,mousemod=0; /* last know mouse coordinates */char *ykey[kLASTKEY+1]; /* keys returned by inkey */#ifdef UNIX#elsestatic DWORD wtid; /* id of win thread */static HANDLE wtevent=INVALID_HANDLE_VALUE; /* handle for win thread event */#endif/* text and font */char *text_align; /* specifies alignement of text */int fontheight; /* height of font in pixel */#ifdef UNIXstatic XFontStruct *myfont; /* properties of default font */#elsestatic LOGFONT logfont; /* structure for font-characteristics */HFONT myfont; /* handle of font for screen */#endif/* general window stuff */static int bitcount; /* stateful counter for bitblit operations */char *foreground=NULL;char *background=NULL;char *geometry=NULL;char *displayname=NULL;char *font=NULL;#ifdef UNIXstatic Display *display; /* X-Display */static Window root; /* ID of root window */static Window window; /* ID of grafic window */static GC gc; /* GC for drawing */static GC rgc; /* GC for reverse drawing */static XSizeHints sizehints; /* hints for window manager */static unsigned long f_color,b_color; /* colors */#elseWNDCLASS myclass; /* window class for my program */HANDLE this_instance;static HDC devcon; /* device context for screen */static HDC bitcon; /* device context backing bitmap */static HBITMAP backbit; /* backing bitmap */char *my_class="my_class";BOOL Commandline; /* true if launched from command line */HANDLE mainthread=INVALID_HANDLE_VALUE; /* handle to main thread */static COLORREF backpixel;static HBRUSH backbrush;static HPEN backpen;HWND window; /* handle of my window */#endif#ifdef UNIX/* variables for redraw coprocess */Pixmap backbit;int backpid=-1; /* pid of process waiting for redraw events */#endif/* ------------- functions ---------------- */void create_openwin(int fnt) /* create Command 'openwin' */{ struct command *cmd; cmd=add_command(cOPENWIN,FALSE); cmd->args=fnt;}void openwin(struct command *cmd) /* open a Window */{ int fnt; static int first=TRUE; /* flag to decide if initialization is necessary */#ifdef UNIX static XEvent event; /* what has happened ? */ XSetWindowAttributes attrib; /* properties of window */ int rx,ry,rw,rh; XGCValues vals; /* values of gc context */ XImage *patch; XWindowAttributes attributes;#endif if (winopened) { error(WARNING,"Window already open"); return; } fnt=cmd->args; if (fnt) { if (font) my_free(font); font=my_strdup(pop(stSTRING)->pointer); } winheight=(int)pop(stNUMBER)->value; if (winheight<1) { error(ERROR,"winheight less than 1 pixel"); return; } winwidth=(int)pop(stNUMBER)->value; if (winwidth<1) { error(ERROR,"winwidth less than 1 pixel"); return; } /* initialize grafics */ if (first && !grafinit()) return; #ifdef UNIX /* create the window */ attrib.backing_store=Always; attrib.save_under=TRUE; attrib.background_pixel=b_color; window=XCreateWindow(display,root,winx,winy,winwidth,winheight,0, CopyFromParent,CopyFromParent,CopyFromParent, CWBackingStore|CWSaveUnder|CWBackPixel, &attrib); if (window==None) { error(ERROR,"Could not create window"); return; } /* put in name for the window */ XStoreName(display,window,progname); /* set size hints */ XSetWMNormalHints(display,window,&sizehints); /* want to get the exposure event */ XSelectInput(display,window,ExposureMask | VisibilityChangeMask); /* display it */ XMapWindow(display,window); /* wait for exposure */ XNextEvent(display,&event); XSelectInput(display,window,0); calc_psscale(); /* create redraw pixmap */ XGetWindowAttributes(display,window,&attributes); backbit=XCreatePixmap(display,window,winwidth,winheight,attributes.depth); if (!backbit) { error(ERROR,"couldn't create backing pixmap"); return; } XFillRectangle(display,window,rgc,0,0,winwidth,winheight); XFillRectangle(display,backbit,rgc,0,0,winwidth,winheight); /* create redraw coprocess */ backpid=fork(); if (backpid==0) { /* this is the child */ display=XOpenDisplay(displayname); XSelectInput(display,window,ExposureMask); XGetGCValues(display,gc,GCPlaneMask,&vals); while(TRUE) { XNextEvent(display,&event); if (event.type==Expose) { rx=event.xexpose.x; ry=event.xexpose.y; rw=event.xexpose.width; rh=event.xexpose.height; patch=XGetImage(display,backbit,rx,ry,rw,rh,vals.plane_mask,ZPixmap); if (patch) { XPutImage(display,window,gc,patch,0,0,rx,ry,rw,rh); free(patch->data); free(patch); } } } } else if (backpid==-1) { error(ERROR,"couldn't fork child"); return; }#else /* WINDOWS */ if (wtevent==INVALID_HANDLE_VALUE) wtevent=CreateEvent(NULL,FALSE,FALSE,"winevent"); ResetEvent(wtevent); /* create thread to care for window */ wthandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)winthread, 0,0,(LPDWORD)&wtid); if (wthandle==NULL) { error(ERROR,"can't create thread for window"); return; } WaitForSingleObject(wtevent,INFINITE); #endif first=FALSE; winopened=TRUE;}#ifdef WINDOWSLRESULT CALLBACK mywindowproc(HWND handle,unsigned msg, UINT wparam,DWORD lparam){ RECT cr; /* client area rectangle */ PAINTSTRUCT ps; /* receives information for painting */ static int wantakey=FALSE; int skey; static char *winkey; char *detail=NULL; int x,y,mod; switch(msg) { case WM_PAINT: if (GetUpdateRect(handle,&cr,0)) { BeginPaint(handle,&ps); devcon=GetDC(handle); BitBlt(devcon,cr.left,cr.top,cr.right-cr.left,cr.bottom-cr.top, bitcon,cr.left,cr.top,SRCCOPY); ReleaseDC(handle,devcon); EndPaint(handle,&ps); SetEvent(wtevent); } return 0; case WM_WANTKEY: /* user wants a key */ winkey=(char *)lparam; wantakey=TRUE; return 0; case WM_LBUTTONDOWN: if (!detail) detail="1d"; case WM_LBUTTONUP: if (!detail) detail="1u"; case WM_RBUTTONDOWN: if (!detail) detail="2d"; case WM_RBUTTONUP: if (!detail) detail="2u"; case WM_MBUTTONDOWN: if (!detail) detail="3d"; case WM_MBUTTONUP: if (!detail) detail="3u"; if (wantakey) { mod=0; if (wparam & MK_CONTROL) mod|=4; if (wparam & MK_SHIFT) mod|=1; mousex=LOWORD(lparam); mousey=HIWORD(lparam); mouseb=atoi(detail); mousemod=mod; x=LOWORD(lparam); y=HIWORD(lparam); itransform(&x,&y); sprintf(winkey,"MB%s+%d:%04d,%04d",detail,mod,x,y); wantakey=FALSE; SetEvent(gotkey); } return 0; case WM_CHAR: if (wantakey) { winkey[0]=wparam; winkey[1]='\0'; SetEvent(gotkey); return 0; } case WM_KEYDOWN: if (wantakey) { skey=-1; switch(wparam) { case VK_UP: skey=kUP;break; case VK_DOWN: skey=kDOWN;break; case VK_LEFT: skey=kLEFT;break; case VK_RIGHT: skey=kRIGHT;break; case VK_DELETE: skey=kDEL;break; case VK_INSERT: skey=kINS;break; case VK_CLEAR: skey=kCLEAR;break; case VK_HOME: skey=kHOME;break; case VK_END: skey=kEND;break; case VK_F1: skey=kF0;break; case VK_F2: skey=kF2;break; case VK_F3: skey=kF3;break; case VK_F4: skey=kF4;break; case VK_F5: skey=kF5;break; case VK_F6: skey=kF6;break; case VK_F7: skey=kF7;break; case VK_F8: skey=kF8;break; case VK_F9: skey=kF9;break; case VK_F10: skey=kF10;break; case VK_F11: skey=kF11;break; case VK_F12: skey=kF12;break; case VK_F13: skey=kF13;break; case VK_F14: skey=kF14;break; case VK_F15: skey=kF15;break; case VK_F16: skey=kF16;break; case VK_F17: skey=kF17;break; case VK_F18: skey=kF18;break; case VK_F19: skey=kF19;break; case VK_F20: skey=kF20;break; case VK_F21: skey=kF21;break; case VK_F22: skey=kF22;break; case VK_F23: skey=kF23;break; case VK_F24: skey=kF24;break; case VK_BACK: skey=kBACKSPACE;break; case VK_PRIOR: skey=kSCRNDOWN;break; case VK_NEXT: skey=kSCRNUP;break; case VK_RETURN: skey=kENTER;break; case VK_ESCAPE: skey=kESC;break; case VK_TAB: skey=kTAB;break; default: break; } if (skey==-1) return(DefWindowProc(handle,msg,wparam,lparam)); strcpy(winkey,ykey[skey]); wantakey=FALSE; SetEvent(gotkey); return 0; } default: return(DefWindowProc(handle,msg,wparam,lparam)); }}static DWORD winthread(LPWORD par) { /* procedure for windows-thread */ MSG msg; int w,h; RECT cr; /* client area rectangle */ winx=winy=30; if (!geometry) geometry=getreg("geometry"); if (geometry) if (sscanf(geometry,"%ix%i+%i+%i",&w,&h,&winx,&winy)!=4 && sscanf(geometry,"+%i+%i",&winx,&winy)!=2 && sscanf(geometry,"%i+%i",&winx,&winy)!=2) winx=winy=30; /* get window-size from client-area size */ cr.left=winx; cr.right=winx+winwidth; cr.top=winy; cr.bottom=winy+winheight; AdjustWindowRect(&cr,WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX,FALSE); /* create my window */ window=CreateWindow(my_class, NULL, /* my style */ WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX,/* window style */ winx, /* initial x-position */ winy, /* initial y-position */ cr.right-cr.left, /* initial x-size */ cr.bottom-cr.top, /* initial y-size */ NULL, /* parent window */ NULL, /* menu handle */ this_instance, /* my instance */ (LPVOID) NULL); /* dont know why */ /* show my window */ sprintf(string,"%s - Grafic Window",progname); SetWindowText(window,string); ShowWindow(this_instance,SW_SHOW); UpdateWindow(this_instance); SetForegroundWindow(window); winopened=TRUE; /* create bitmap device context */ devcon=GetDC(window); bitcon=CreateCompatibleDC(devcon); cr.left=cr.top=0; cr.right=winwidth; cr.bottom=winheight; backbit=CreateCompatibleBitmap(devcon,cr.right-cr.left,cr.bottom-cr.top); SelectObject(bitcon,backbit); SelectClipRgn(bitcon,NULL); IntersectClipRect(bitcon,0,0,winwidth,winheight); FillRect(bitcon,&cr,(HBRUSH)COLOR_WINDOW); backpixel=GetPixel(bitcon,0,0); backbrush=CreateSolidBrush(backpixel); SelectObject(bitcon,GetStockObject(BLACK_PEN)); ReleaseDC(window,devcon); /* create pen for windows */ backpen=CreatePen(PS_SOLID,0,backpixel); /* get and dispatch messages */ while(GetMessage((LPMSG)&msg,NULL,0,0)) { TranslateMessage((LPMSG)&msg); DispatchMessage((LPMSG)&msg); } /* delete all those objects */ DestroyWindow(window); DeleteObject(backbit); DeleteObject(backpen); DeleteObject(backbrush); DeleteDC(devcon); DeleteDC(bitcon); ExitThread(0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -