📄 graphic.c
字号:
/* YABASIC --- a simple Basic Interpreter written by Marc-Oliver Ihm 1995-2005 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 char *newrgb (int, int); /* create a new bitmap string */static void addrgb (char *, unsigned short, unsigned short, unsigned short); /* add one rgb pixel to bitstring */static int readrgb (char *, unsigned short *, unsigned short *, unsigned short *); /* read rgb pixel from string one after another */static int change_font (char *); /* change font */#ifdef WINDOWSstatic DWORD winthread (LPWORD); /* window thread */static void startdraw (int); /* prepare for drawing */static void enddraw (); /* end of 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 WINDOWSstatic LOGFONT logfont; /* structure for font-characteristics */HFONT 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 */#ifdef UNIXstatic XFontStruct *myfont = NULL; /* properties of default font */#elseHFONT myfont; /* handle of font for screen */#endif/* 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 */static HANDLE drawmutex = INVALID_HANDLE_VALUE; /* handle for drawing mutex */#endif/* text and font */char *text_align; /* specifies alignement of text */int fontheight; /* height of font in pixel *//* 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 unsigned long forepixel, backpixel; /* colors */static 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 */#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 COLORREF forepixel;static HBRUSH backbrush;static HBRUSH forebrush;static HPEN backpen;static HPEN forepen;static HGDIOBJ saveddevbrush;static HGDIOBJ saveddevpen;static HGDIOBJ savedbitbrush;static HGDIOBJ savedbitpen;static HGDIOBJ savedprnpen;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 */Colormap colormap; /* colormap for this visual */XVisualInfo visualinfo; /* visual info; contains masks for red, green and blue */static unsigned long rbits_shift = 0; /* position of red bits within pixel value */static unsigned long gbits_shift = 0; /* same for green */static unsigned long bbits_shift = 0; /* same for blue */static unsigned long rbits_max = 0; /* number of red bits within pixel value */static unsigned long gbits_max = 0; /* same for green */static unsigned long bbits_max = 0; /* same for blue */#endif/* ------------- functions ---------------- */voidcreate_openwin (int fnt){ /* create Command 'openwin' */ struct command *cmd; cmd = add_command (cOPENWIN, FALSE); cmd->args = fnt;}voidopenwin (struct command *cmd){ /* open a Window */ int fnt; static int first = TRUE; /* flag to decide if initialization is necessary */ char *f = NULL;#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; XColor colour; int r, g, b;#endif if (winopened) { error (WARNING, "Window already open"); return; } fnt = cmd->args; if (fnt) f = (char *) 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; if (f && !change_font (f)) return;#ifdef UNIX /* create the window */ attrib.backing_store = Always; attrib.save_under = TRUE; attrib.background_pixel = backpixel; attrib.colormap = colormap; window = XCreateWindow (display, root, winx, winy, winwidth, winheight, 0, CopyFromParent, CopyFromParent, visualinfo.visual, CWBackingStore | CWSaveUnder | CWBackPixel | CWColormap, &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"); if (drawmutex == INVALID_HANDLE_VALUE) drawmutex = CreateMutex (NULL, FALSE, "drawmutex"); 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 CALLBACKmywindowproc (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)) { WaitForSingleObject (drawmutex, INFINITE); if (!BeginPaint (handle, &ps)) return 1; BitBlt (ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, bitcon, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); EndPaint (handle, &ps); ReleaseMutex (drawmutex); 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -