📄 x_sherry.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp> Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA x_sherry.c - Sherry WRD for X Window written by Masanao Izumo*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#ifdef ENABLE_SHERRY#include <X11/Xlib.h>#include <X11/Xutil.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <stdlib.h>#include <png.h>#include "timidity.h"#include "common.h"#include "controls.h"#include "wrd.h"#include "aq.h"#include "x_sherry.h"#ifndef XSHM_SUPPORT#if defined(HAVE_XSHMCREATEPIXMAP) && \ defined(HAVE_X11_EXTENSIONS_XSHM_H) && \ defined(HAVE_SYS_IPC_H) && \ defined(HAVE_SYS_SHM_H)#define XSHM_SUPPORT 1#else#define XSHM_SUPPORT 0#endif#endif /* XSHM_SUPPORT */#if XSHM_SUPPORT#include <X11/extensions/XShm.h>#include <sys/ipc.h>#include <sys/shm.h>#endif#define MAX_PLANES 8#define MAX_COLORS (1<<MAX_PLANES)#define MAX_VIRTUAL_SCREENS 65536#define MAX_PALETTES 256#define MAX_VIRTUAL_PALETTES 65536#define REAL_SCREEN_SIZE_X 640#define REAL_SCREEN_SIZE_Y 480#define CHAR_WIDTH1 8#define CHAR_WIDTH2 16#define CHAR_HEIGHT 16#define SHERRY_MAX_VALUE 65536#define JISX0201 "-*-fixed-*-r-normal--16-*-*-*-*-*-jisx0201.1976-*"#define JISX0208 "-*-fixed-*-r-normal--16-*-*-*-*-*-jisx0208.1983-*"/* (mask & src) | (~mask & dst) equals as Windows API BitBlt ROP 0x00CA0749 *//* #define ROP3_CA0749(ptn, src, dst) (((ptn) & (src)) | (~(ptn) & (dst))) */#define ROP3_CA0749(ptn, src, dst) ((dst) ^ ((ptn) & ((src) ^ (dst))))typedef struct _ImagePixmap{ Pixmap pm; XImage *im; GC gc; int depth;#if XSHM_SUPPORT XShmSegmentInfo shminfo;#endif /* XSHM_SUPPORT */} ImagePixmap;typedef struct _VirtualScreen{ uint16 width, height; uint8 transParent; uint8 data[1]; /* Pseudo 256 color, size = width * height */} VirtualScreen;typedef struct _SherryPaletteEntry{ uint8 r; uint8 g; uint8 b;} SherryPaletteEntry;typedef struct _SherryPalette{ SherryPaletteEntry entry[MAX_PALETTES];} SherryPalette;static Display *theDisplay;static int theScreen;/* real screen */static Window theWindow;static ImagePixmap *theRealScreen;static Visual *theVisual; /* Visual of main window */static Colormap theColormap; /* Colormap of main window */static int theDepth; /* Depth of main window */static int theClass; /* Visual class */static XFontStruct *theFont8; /* 8bit Font */static XFontStruct *theFont16; /* 16bit Font */static int lbearing8, lbearing16, ascent8, ascent16;static GC theGC;/* For memory draw string */#define IMAGEBITMAPLEN 40static ImagePixmap *imageBitmap;static int bitmap_drawimage(ImagePixmap *ip, char *sjis_str, int nbytes);static VirtualScreen **virtualScreen; /* MAX_VIRTUAL_SCREENS */static VirtualScreen *tmpScreen;static VirtualScreen *alloc_vscreen(int width, int height, int transParent);static void free_vscreen(VirtualScreen *scr);#define VSCREEN_PIXEL(scr, x, y) ((scr)->data[(scr)->width * (y) + (x)])static unsigned long basePixel; /* base pixel */static unsigned long planePixel[MAX_PLANES]; /* plane pixel */static unsigned long palette2Pixel[MAX_COLORS];static int currentPalette;static SherryPalette **virtualPalette; /* MAX_VIRTUAL_PALETTES, 簿鳞パレット */static SherryPaletteEntry realPalette[MAX_PALETTES];static uint8 *pseudoImage = NULL; /* For TrueColor */static int draw_ctl_flag = True;static int err_to_stop = 0;/* Image Pixmap */static ImagePixmap *create_image_pixmap(int width, int height, int depth);static void clear_image_pixmap(ImagePixmap *ip, unsigned long pixel);static void free_image_pixmap(ImagePixmap *ip);#if XSHM_SUPPORTstatic ImagePixmap *create_shm_image_pixmap(int width, int height, int depth);#endif /* XSHM_SUPPORT */static int isRealPaletteChanged, isRealScreenChanged;static int updateClipX1, updateClipY1, updateClipX2, updateClipY2;static int check_range(VirtualScreen *scr, int x1, int y1, int x2, int y2);static Window try_create_window(Display *disp, int width, int height, int want_class, int want_depth, Visual **newVisual, Colormap *newColormap){ Visual *defVisual; int defScreen; int defDepth; XSetWindowAttributes xswa; unsigned long xswamask; int numvis; defScreen = DefaultScreen(disp); defVisual = DefaultVisual(disp, defScreen); defDepth = DefaultDepth(disp, defScreen); if(want_class == -1) want_class = defVisual->class; if(want_depth == -1) want_depth = defDepth; if(defVisual->class == want_class && defDepth == want_depth) *newVisual = defVisual; else { XVisualInfo *vinfo, rvinfo; rvinfo.class = want_class; rvinfo.screen = defScreen; rvinfo.depth = want_depth; vinfo = XGetVisualInfo(disp, VisualClassMask | VisualScreenMask | VisualDepthMask, &rvinfo, &numvis); if(vinfo == NULL) return None; if(numvis == 0) { XFree((char *)vinfo); return None; } *newVisual = vinfo[0].visual; } *newColormap = XCreateColormap(disp, RootWindow(disp, defScreen), *newVisual, AllocNone); xswa.background_pixel = 0; xswa.border_pixel = 0; xswa.colormap = *newColormap; xswamask = CWBackPixel | CWBorderPixel | CWColormap; return XCreateWindow(disp, RootWindow(disp, defScreen), 0, 0, width, height, 0, want_depth, InputOutput, *newVisual, xswamask, &xswa);}/* Create real-screen for Sherry WRD Window * sutable theVisual, theColormap, theDepth, theClass is selected. */static Window create_main_window(int want_class, int want_depth){ Window win; int i; struct { int want_class, want_depth; } target_visuals[] = { {TrueColor, 24}, {TrueColor, 32}, {TrueColor, 16}, {PseudoColor, 8}, {-1, -1}}; if(want_class != -1) { win = try_create_window(theDisplay, REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y, want_class, want_depth, &theVisual, &theColormap); theClass = want_class; theDepth = want_depth; return win; } for(i = 0; target_visuals[i].want_class != -1; i++) if((win = try_create_window(theDisplay, REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y, target_visuals[i].want_class, target_visuals[i].want_depth, &theVisual, &theColormap)) != None) { theClass = target_visuals[i].want_class; theDepth = target_visuals[i].want_depth; return win; } /* Use default visual */ if((win = try_create_window(theDisplay, REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y, -1, -1, &theVisual, &theColormap)) != None) { theClass = theVisual->class; theDepth = DefaultDepth(theDisplay, theScreen); return win; } return None;}static GC createGC(Display *disp, Drawable draw){ XGCValues gv; gv.graphics_exposures = False; return XCreateGC(disp, draw, GCGraphicsExposures, &gv);}static int highbit(unsigned long ul){ int i; unsigned long hb; hb = 0x80000000UL; for(i = 31; ((ul & hb) == 0) && i >= 0; i--, ul<<=1) ; return i;}static inline unsigned long trueColorPixel(unsigned long r, /* 0..255 */ unsigned long g, /* 0..255 */ unsigned long b) /* 0..255 */{ static int rs, gs, bs; if(r == 0xffffffff) /* for initialize */ { rs = 15 - highbit(theVisual->red_mask); gs = 15 - highbit(theVisual->green_mask); bs = 15 - highbit(theVisual->blue_mask); return 0; } r *= 257; /* 0..65535 */ g *= 257; /* 0..65535 */ b *= 257; /* 0..65535 */ if(rs < 0) r <<= -rs; else r >>= rs; if(gs < 0) g <<= -gs; else g >>= gs; if(bs < 0) b <<= -bs; else b >>= bs; r &= theVisual->red_mask; g &= theVisual->green_mask; b &= theVisual->blue_mask; return r | g | b;}static Bool init_palette(void){ static int first_flag = 1; int i, j; XColor xcolors[MAX_COLORS]; if(first_flag) { first_flag = 0; if(theClass == TrueColor) { basePixel = 0; trueColorPixel(0xffffffff, 0, 0); return True; } if(!XAllocColorCells(theDisplay, theColormap, False, planePixel, MAX_PLANES, &basePixel, 1)) return False; } if(theClass == TrueColor) return True; for(i = 0; i < MAX_COLORS; i++) { palette2Pixel[i] = basePixel; for(j = 0; j < MAX_PLANES; j++) if((i & (1 << j)) != 0) palette2Pixel[i] |= planePixel[j]; } for(i = 0; i < MAX_COLORS; i++) { xcolors[i].pixel = palette2Pixel[i]; xcolors[i].red = 0; xcolors[i].green = 0; xcolors[i].blue = 0; xcolors[i].flags = DoRed | DoGreen | DoBlue; } XStoreColors(theDisplay, theColormap, xcolors, MAX_COLORS); return True;}static Bool init_font(void){ if((theFont8 = XLoadQueryFont(theDisplay, JISX0201)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Can't load font", JISX0201); return False; } if((theFont16 = XLoadQueryFont(theDisplay, JISX0208)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Can't load font", JISX0208); XFreeFont(theDisplay, theFont8); return False; } lbearing8 = theFont8->min_bounds.lbearing; ascent8 = theFont8->max_bounds.ascent; lbearing16 = theFont16->min_bounds.lbearing; ascent16 = theFont16->max_bounds.ascent; return True;}static void free_font(void){ XFreeFont(theDisplay, theFont8); XFreeFont(theDisplay, theFont16);}/* open *//* return: * -1: error * 0: success * 1: already initialized */static int x_sry_open(char *opts){ static Bool error_flag = False; int i; Bool try_pseudo; if(error_flag) { if(error_flag == -1) ctl->cmsg(CMSG_ERROR, VERB_NOISY, "Sherry WRD: Can't work because of error"); else if(error_flag == 1) /* Already initialized */ { XMapWindow(theDisplay, theWindow); clear_image_pixmap(theRealScreen, basePixel); XFlush(theDisplay); return 0; } return error_flag; } try_pseudo = 0; if(opts) { if(strchr(opts, 'p')) try_pseudo = 1; } if((theDisplay = XOpenDisplay(NULL)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Sherry WRD: Can't open display: %s", XDisplayName(NULL)); error_flag = -1; return -1; } if(!init_font()) { XCloseDisplay(theDisplay); theDisplay = NULL; error_flag = -1; return -1; } theScreen = DefaultScreen(theDisplay); if(try_pseudo) theWindow = create_main_window(PseudoColor, 8); else theWindow = create_main_window(-1, -1); if(theWindow == None) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Sherry WRD: Can't create Sherry WRD Window"); free_font(); XCloseDisplay(theDisplay); theDisplay = NULL; error_flag = -1; return -1; } XSelectInput(theDisplay, theWindow, ExposureMask);#if XSHM_SUPPORT theRealScreen = create_shm_image_pixmap(REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y, theDepth); imageBitmap = create_shm_image_pixmap(IMAGEBITMAPLEN * CHAR_WIDTH1, CHAR_HEIGHT, theDepth);#else theRealScreen = create_image_pixmap(REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y, theDepth); imageBitmap = create_image_pixmap(IMAGEBITMAPLEN * CHAR_WIDTH1, CHAR_HEIGHT, 1);#endif init_palette(); XSetWindowBackground(theDisplay, theWindow, basePixel); XSetForeground(theDisplay, imageBitmap->gc, 1); XSetBackground(theDisplay, imageBitmap->gc, 0); theGC = createGC(theDisplay, theWindow); virtualScreen = (VirtualScreen **)safe_malloc(MAX_VIRTUAL_SCREENS * sizeof(VirtualScreen *)); for(i = 0; i < MAX_VIRTUAL_SCREENS; i++) virtualScreen[i] = NULL; tmpScreen = NULL; virtualPalette = (SherryPalette **)safe_malloc(MAX_VIRTUAL_PALETTES * sizeof(SherryPalette *)); for(i = 0; i < MAX_VIRTUAL_PALETTES; i++) virtualPalette[i] = NULL; memset(realPalette, 0, sizeof(realPalette)); if(theClass == TrueColor) { pseudoImage = (uint8 *)safe_malloc(REAL_SCREEN_SIZE_X * REAL_SCREEN_SIZE_Y); memset(pseudoImage, 0, REAL_SCREEN_SIZE_X * REAL_SCREEN_SIZE_Y); } XMapWindow(theDisplay, theWindow); XFlush(theDisplay); error_flag = 1; return 0;}void CloseSryWindow(void){ XUnmapWindow(theDisplay, theWindow); XFlush(theDisplay);}int OpenSryWindow(char *opts){ return x_sry_open(opts);}void x_sry_close(void){ int i; if(theDisplay == NULL) return; free_image_pixmap(theRealScreen); free_image_pixmap(imageBitmap); for(i = 0; i < MAX_VIRTUAL_SCREENS; i++) if(virtualScreen[i] != NULL) { free_vscreen(virtualScreen[i]); virtualScreen[i] = NULL; } free(virtualScreen); if(tmpScreen != NULL) { free(tmpScreen); tmpScreen = NULL; } for(i = 0; i < MAX_VIRTUAL_PALETTES; i++) if(virtualPalette[i] != NULL) { free(virtualPalette[i]); virtualPalette[i] = NULL; } free(virtualPalette); if(pseudoImage) free(pseudoImage); XFreeFont(theDisplay, theFont8); XFreeFont(theDisplay, theFont16); XCloseDisplay(theDisplay); theDisplay = NULL;}static void sry_new_vpal(uint8 *data, int len){ int i, n; for(i = 0; i < len-1; i += 2) { n = SRY_GET_SHORT(data + i) & 0xffff;#ifdef SRY_DEBUG printf("NEW palette %d\n", n);#endif /* SRY_DEBUG */ if(virtualPalette[n] == NULL) virtualPalette[n] = (SherryPalette *)safe_malloc(sizeof(SherryPalette)); memset(virtualPalette[n], 0, sizeof(SherryPalette)); }}static void sry_free_vpal(uint8 *data, int len){ int i, n; for(i = 0; i < len-1; i += 2) { n = SRY_GET_SHORT(data + i) & 0xffff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -