1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 x_sherry.c - Sherry WRD for X Window written by Masanao Izumo
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif /* HAVE_CONFIG_H */
26
27 #ifdef ENABLE_SHERRY
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 #ifndef NO_STRING_H
31 #include <string.h>
32 #else
33 #include <strings.h>
34 #endif
35 #include <stdlib.h>
36 #include <png.h>
37
38 #include "timidity.h"
39 #include "common.h"
40 #include "controls.h"
41 #include "wrd.h"
42 #include "aq.h"
43 #include "x_sherry.h"
44
45 #ifndef XSHM_SUPPORT
46 #if defined(HAVE_XSHMCREATEPIXMAP) && \
47 defined(HAVE_X11_EXTENSIONS_XSHM_H) && \
48 defined(HAVE_SYS_IPC_H) && \
49 defined(HAVE_SYS_SHM_H)
50 #define XSHM_SUPPORT 1
51 #else
52 #define XSHM_SUPPORT 0
53 #endif
54 #endif /* XSHM_SUPPORT */
55
56 #if XSHM_SUPPORT
57 #include <X11/extensions/XShm.h>
58 #include <sys/ipc.h>
59 #include <sys/shm.h>
60 #endif
61
62 #define MAX_PLANES 8
63 #define MAX_COLORS (1<<MAX_PLANES)
64 #define MAX_VIRTUAL_SCREENS 65536
65 #define MAX_PALETTES 256
66 #define MAX_VIRTUAL_PALETTES 65536
67 #define REAL_SCREEN_SIZE_X 640
68 #define REAL_SCREEN_SIZE_Y 480
69 #define CHAR_WIDTH1 8
70 #define CHAR_WIDTH2 16
71 #define CHAR_HEIGHT 16
72 #define SHERRY_MAX_VALUE 65536
73 #define JISX0201 "-*-fixed-*-r-normal--16-*-*-*-*-*-jisx0201.1976-*"
74 #define JISX0208 "-*-fixed-*-r-normal--16-*-*-*-*-*-jisx0208.1983-*"
75
76 /* (mask & src) | (~mask & dst) equals as Windows API BitBlt ROP 0x00CA0749 */
77 /* #define ROP3_CA0749(ptn, src, dst) (((ptn) & (src)) | (~(ptn) & (dst))) */
78 #define ROP3_CA0749(ptn, src, dst) ((dst) ^ ((ptn) & ((src) ^ (dst))))
79
80 typedef struct _ImagePixmap
81 {
82 Pixmap pm;
83 XImage *im;
84 GC gc;
85 int depth;
86 #if XSHM_SUPPORT
87 XShmSegmentInfo shminfo;
88 #endif /* XSHM_SUPPORT */
89 } ImagePixmap;
90
91 typedef struct _VirtualScreen
92 {
93 uint16 width, height;
94 uint8 transParent;
95 uint8 data[1]; /* Pseudo 256 color, size = width * height */
96 } VirtualScreen;
97
98 typedef struct _SherryPaletteEntry
99 {
100 uint8 r;
101 uint8 g;
102 uint8 b;
103 } SherryPaletteEntry;
104
105 typedef struct _SherryPalette
106 {
107 SherryPaletteEntry entry[MAX_PALETTES];
108 } SherryPalette;
109
110
111 static Display *theDisplay;
112 static int theScreen;
113
114 /* real screen */
115 static Window theWindow;
116 static ImagePixmap *theRealScreen;
117 static Visual *theVisual; /* Visual of main window */
118 static Colormap theColormap; /* Colormap of main window */
119 static int theDepth; /* Depth of main window */
120 static int theClass; /* Visual class */
121 static XFontStruct *theFont8; /* 8bit Font */
122 static XFontStruct *theFont16; /* 16bit Font */
123 static int lbearing8, lbearing16, ascent8, ascent16;
124 static GC theGC;
125
126 /* For memory draw string */
127 #define IMAGEBITMAPLEN 40
128 static ImagePixmap *imageBitmap;
129 static int bitmap_drawimage(ImagePixmap *ip, char *sjis_str, int nbytes);
130
131
132 static VirtualScreen **virtualScreen; /* MAX_VIRTUAL_SCREENS */
133 static VirtualScreen *tmpScreen;
134 static VirtualScreen *alloc_vscreen(int width, int height, int transParent);
135 static void free_vscreen(VirtualScreen *scr);
136
137 #define VSCREEN_PIXEL(scr, x, y) ((scr)->data[(scr)->width * (y) + (x)])
138
139 static unsigned long basePixel; /* base pixel */
140 static unsigned long planePixel[MAX_PLANES]; /* plane pixel */
141 static unsigned long palette2Pixel[MAX_COLORS];
142 static int currentPalette;
143
144 static SherryPalette **virtualPalette; /* MAX_VIRTUAL_PALETTES, ���ۥѥ�å� */
145 static SherryPaletteEntry realPalette[MAX_PALETTES];
146 static uint8 *pseudoImage = NULL; /* For TrueColor */
147
148 static int draw_ctl_flag = True;
149 static int err_to_stop = 0;
150
151
152 /* Image Pixmap */
153 static ImagePixmap *create_image_pixmap(int width, int height, int depth);
154 static void clear_image_pixmap(ImagePixmap *ip, unsigned long pixel);
155 static void free_image_pixmap(ImagePixmap *ip);
156
157 #if XSHM_SUPPORT
158 static ImagePixmap *create_shm_image_pixmap(int width, int height, int depth);
159 #endif /* XSHM_SUPPORT */
160
161 static int isRealPaletteChanged, isRealScreenChanged;
162 static int updateClipX1, updateClipY1, updateClipX2, updateClipY2;
163
164 static int check_range(VirtualScreen *scr, int x1, int y1, int x2, int y2);
165
166
try_create_window(Display * disp,int width,int height,int want_class,int want_depth,Visual ** newVisual,Colormap * newColormap)167 static Window try_create_window(Display *disp, int width, int height,
168 int want_class, int want_depth,
169 Visual **newVisual,
170 Colormap *newColormap)
171 {
172 Visual *defVisual;
173 int defScreen;
174 int defDepth;
175
176 XSetWindowAttributes xswa;
177 unsigned long xswamask;
178 int numvis;
179
180 defScreen = DefaultScreen(disp);
181 defVisual = DefaultVisual(disp, defScreen);
182 defDepth = DefaultDepth(disp, defScreen);
183
184 if(want_class == -1)
185 want_class = defVisual->class;
186 if(want_depth == -1)
187 want_depth = defDepth;
188
189 if(defVisual->class == want_class && defDepth == want_depth)
190 *newVisual = defVisual;
191 else
192 {
193 XVisualInfo *vinfo, rvinfo;
194
195 rvinfo.class = want_class;
196 rvinfo.screen = defScreen;
197 rvinfo.depth = want_depth;
198 vinfo = XGetVisualInfo(disp,
199 VisualClassMask |
200 VisualScreenMask |
201 VisualDepthMask,
202 &rvinfo, &numvis);
203 if(vinfo == NULL)
204 return None;
205 if(numvis == 0)
206 {
207 XFree((char *)vinfo);
208 return None;
209 }
210
211 *newVisual = vinfo[0].visual;
212 }
213 *newColormap = XCreateColormap(disp,
214 RootWindow(disp, defScreen),
215 *newVisual, AllocNone);
216
217 xswa.background_pixel = 0;
218 xswa.border_pixel = 0;
219 xswa.colormap = *newColormap;
220 xswamask = CWBackPixel | CWBorderPixel | CWColormap;
221 return XCreateWindow(disp, RootWindow(disp, defScreen),
222 0, 0, width, height, 0, want_depth,
223 InputOutput, *newVisual, xswamask, &xswa);
224 }
225
226
227 /* Create real-screen for Sherry WRD Window
228 * sutable theVisual, theColormap, theDepth, theClass is selected.
229 */
create_main_window(int want_class,int want_depth)230 static Window create_main_window(int want_class, int want_depth)
231 {
232 Window win;
233 int i;
234 struct {
235 int want_class, want_depth;
236 } target_visuals[] = {
237 {TrueColor, 24},
238 {TrueColor, 32},
239 {TrueColor, 16},
240 {PseudoColor, 8},
241 {-1, -1}};
242
243 if(want_class != -1)
244 {
245 win = try_create_window(theDisplay,
246 REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y,
247 want_class, want_depth,
248 &theVisual, &theColormap);
249 theClass = want_class;
250 theDepth = want_depth;
251 return win;
252 }
253
254 for(i = 0; target_visuals[i].want_class != -1; i++)
255 if((win = try_create_window(theDisplay,
256 REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y,
257 target_visuals[i].want_class,
258 target_visuals[i].want_depth,
259 &theVisual, &theColormap)) != None)
260 {
261 theClass = target_visuals[i].want_class;
262 theDepth = target_visuals[i].want_depth;
263 return win;
264 }
265
266 /* Use default visual */
267 if((win = try_create_window(theDisplay,
268 REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y,
269 -1, -1, &theVisual, &theColormap)) != None)
270 {
271 theClass = theVisual->class;
272 theDepth = DefaultDepth(theDisplay, theScreen);
273 return win;
274 }
275 return None;
276 }
277
createGC(Display * disp,Drawable draw)278 static GC createGC(Display *disp, Drawable draw)
279 {
280 XGCValues gv;
281 gv.graphics_exposures = False;
282 return XCreateGC(disp, draw, GCGraphicsExposures, &gv);
283 }
284
highbit(unsigned long ul)285 static int highbit(unsigned long ul)
286 {
287 int i; unsigned long hb;
288 hb = 0x80000000UL;
289 for(i = 31; ((ul & hb) == 0) && i >= 0; i--, ul<<=1)
290 ;
291 return i;
292 }
293
trueColorPixel(unsigned long r,unsigned long g,unsigned long b)294 static inline unsigned long trueColorPixel(unsigned long r, /* 0..255 */
295 unsigned long g, /* 0..255 */
296 unsigned long b) /* 0..255 */
297 {
298 static int rs, gs, bs;
299
300 if(r == 0xffffffff) /* for initialize */
301 {
302 rs = 15 - highbit(theVisual->red_mask);
303 gs = 15 - highbit(theVisual->green_mask);
304 bs = 15 - highbit(theVisual->blue_mask);
305 return 0;
306 }
307
308 r *= 257; /* 0..65535 */
309 g *= 257; /* 0..65535 */
310 b *= 257; /* 0..65535 */
311 if(rs < 0) r <<= -rs;
312 else r >>= rs;
313 if(gs < 0) g <<= -gs;
314 else g >>= gs;
315 if(bs < 0) b <<= -bs;
316 else b >>= bs;
317 r &= theVisual->red_mask;
318 g &= theVisual->green_mask;
319 b &= theVisual->blue_mask;
320
321 return r | g | b;
322 }
323
init_palette(void)324 static Bool init_palette(void)
325 {
326 static int first_flag = 1;
327 int i, j;
328 XColor xcolors[MAX_COLORS];
329
330 if(first_flag)
331 {
332 first_flag = 0;
333
334 if(theClass == TrueColor)
335 {
336 basePixel = 0;
337 trueColorPixel(0xffffffff, 0, 0);
338 return True;
339 }
340
341 if(!XAllocColorCells(theDisplay, theColormap, False,
342 planePixel, MAX_PLANES,
343 &basePixel, 1))
344 return False;
345 }
346
347 if(theClass == TrueColor)
348 return True;
349
350 for(i = 0; i < MAX_COLORS; i++)
351 {
352 palette2Pixel[i] = basePixel;
353 for(j = 0; j < MAX_PLANES; j++)
354 if((i & (1 << j)) != 0) palette2Pixel[i] |= planePixel[j];
355 }
356
357 for(i = 0; i < MAX_COLORS; i++)
358 {
359 xcolors[i].pixel = palette2Pixel[i];
360 xcolors[i].red = 0;
361 xcolors[i].green = 0;
362 xcolors[i].blue = 0;
363 xcolors[i].flags = DoRed | DoGreen | DoBlue;
364 }
365 XStoreColors(theDisplay, theColormap, xcolors, MAX_COLORS);
366 return True;
367 }
368
init_font(void)369 static Bool init_font(void)
370 {
371 if((theFont8 = XLoadQueryFont(theDisplay, JISX0201)) == NULL)
372 {
373 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Can't load font", JISX0201);
374 return False;
375 }
376 if((theFont16 = XLoadQueryFont(theDisplay, JISX0208)) == NULL)
377 {
378 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Can't load font", JISX0208);
379 XFreeFont(theDisplay, theFont8);
380 return False;
381 }
382
383 lbearing8 = theFont8->min_bounds.lbearing;
384 ascent8 = theFont8->max_bounds.ascent;
385 lbearing16 = theFont16->min_bounds.lbearing;
386 ascent16 = theFont16->max_bounds.ascent;
387
388 return True;
389 }
390
free_font(void)391 static void free_font(void)
392 {
393 XFreeFont(theDisplay, theFont8);
394 XFreeFont(theDisplay, theFont16);
395 }
396
397 /* open */
398 /* return:
399 * -1: error
400 * 0: success
401 * 1: already initialized
402 */
x_sry_open(char * opts)403 static int x_sry_open(char *opts)
404 {
405 static Bool error_flag = False;
406 int i;
407 Bool try_pseudo;
408
409 if(error_flag)
410 {
411 if(error_flag == -1)
412 ctl->cmsg(CMSG_ERROR, VERB_NOISY,
413 "Sherry WRD: Can't work because of error");
414 else if(error_flag == 1) /* Already initialized */
415 {
416 XMapWindow(theDisplay, theWindow);
417 clear_image_pixmap(theRealScreen, basePixel);
418 XFlush(theDisplay);
419 return 0;
420 }
421 return error_flag;
422 }
423
424 try_pseudo = 0;
425 if(opts)
426 {
427 if(strchr(opts, 'p'))
428 try_pseudo = 1;
429 }
430
431 if((theDisplay = XOpenDisplay(NULL)) == NULL)
432 {
433 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
434 "Sherry WRD: Can't open display: %s", XDisplayName(NULL));
435 error_flag = -1;
436 return -1;
437 }
438
439 if(!init_font())
440 {
441 XCloseDisplay(theDisplay);
442 theDisplay = NULL;
443 error_flag = -1;
444 return -1;
445 }
446
447 theScreen = DefaultScreen(theDisplay);
448 if(try_pseudo)
449 theWindow = create_main_window(PseudoColor, 8);
450 else
451 theWindow = create_main_window(-1, -1);
452 if(theWindow == None)
453 {
454 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
455 "Sherry WRD: Can't create Sherry WRD Window");
456 free_font();
457 XCloseDisplay(theDisplay);
458 theDisplay = NULL;
459 error_flag = -1;
460 return -1;
461 }
462 XSelectInput(theDisplay, theWindow, ExposureMask);
463
464 #if XSHM_SUPPORT
465 theRealScreen = create_shm_image_pixmap(REAL_SCREEN_SIZE_X,
466 REAL_SCREEN_SIZE_Y,
467 theDepth);
468 imageBitmap = create_shm_image_pixmap(IMAGEBITMAPLEN * CHAR_WIDTH1,
469 CHAR_HEIGHT,
470 theDepth);
471 #else
472 theRealScreen = create_image_pixmap(REAL_SCREEN_SIZE_X,
473 REAL_SCREEN_SIZE_Y,
474 theDepth);
475 imageBitmap = create_image_pixmap(IMAGEBITMAPLEN * CHAR_WIDTH1,
476 CHAR_HEIGHT,
477 1);
478 #endif
479
480 init_palette();
481 XSetWindowBackground(theDisplay, theWindow, basePixel);
482 XSetForeground(theDisplay, imageBitmap->gc, 1);
483 XSetBackground(theDisplay, imageBitmap->gc, 0);
484
485 theGC = createGC(theDisplay, theWindow);
486
487 virtualScreen = (VirtualScreen **)safe_malloc(MAX_VIRTUAL_SCREENS *
488 sizeof(VirtualScreen *));
489 for(i = 0; i < MAX_VIRTUAL_SCREENS; i++)
490 virtualScreen[i] = NULL;
491 tmpScreen = NULL;
492
493 virtualPalette = (SherryPalette **)safe_malloc(MAX_VIRTUAL_PALETTES *
494 sizeof(SherryPalette *));
495 for(i = 0; i < MAX_VIRTUAL_PALETTES; i++)
496 virtualPalette[i] = NULL;
497 memset(realPalette, 0, sizeof(realPalette));
498
499 if(theClass == TrueColor)
500 {
501 pseudoImage = (uint8 *)safe_malloc(REAL_SCREEN_SIZE_X *
502 REAL_SCREEN_SIZE_Y);
503 memset(pseudoImage, 0, REAL_SCREEN_SIZE_X * REAL_SCREEN_SIZE_Y);
504 }
505
506 XMapWindow(theDisplay, theWindow);
507 XFlush(theDisplay);
508 error_flag = 1;
509
510 return 0;
511 }
512
CloseSryWindow(void)513 void CloseSryWindow(void)
514 {
515 XUnmapWindow(theDisplay, theWindow);
516 XFlush(theDisplay);
517 }
518
OpenSryWindow(char * opts)519 int OpenSryWindow(char *opts)
520 {
521 return x_sry_open(opts);
522 }
523
x_sry_close(void)524 void x_sry_close(void)
525 {
526 int i;
527
528 if(theDisplay == NULL)
529 return;
530 free_image_pixmap(theRealScreen);
531 free_image_pixmap(imageBitmap);
532 for(i = 0; i < MAX_VIRTUAL_SCREENS; i++)
533 if(virtualScreen[i] != NULL)
534 {
535 free_vscreen(virtualScreen[i]);
536 virtualScreen[i] = NULL;
537 }
538 free(virtualScreen);
539 if(tmpScreen != NULL)
540 {
541 free(tmpScreen);
542 tmpScreen = NULL;
543 }
544 for(i = 0; i < MAX_VIRTUAL_PALETTES; i++)
545 if(virtualPalette[i] != NULL)
546 {
547 free(virtualPalette[i]);
548 virtualPalette[i] = NULL;
549 }
550 free(virtualPalette);
551 if(pseudoImage)
552 free(pseudoImage);
553 XFreeFont(theDisplay, theFont8);
554 XFreeFont(theDisplay, theFont16);
555 XCloseDisplay(theDisplay);
556 theDisplay = NULL;
557 }
558
sry_new_vpal(uint8 * data,int len)559 static void sry_new_vpal(uint8 *data, int len)
560 {
561 int i, n;
562
563 for(i = 0; i < len-1; i += 2)
564 {
565 n = SRY_GET_SHORT(data + i) & 0xffff;
566 #ifdef SRY_DEBUG
567 printf("NEW palette %d\n", n);
568 #endif /* SRY_DEBUG */
569 if(virtualPalette[n] == NULL)
570 virtualPalette[n] =
571 (SherryPalette *)safe_malloc(sizeof(SherryPalette));
572 memset(virtualPalette[n], 0, sizeof(SherryPalette));
573 }
574 }
575
sry_free_vpal(uint8 * data,int len)576 static void sry_free_vpal(uint8 *data, int len)
577 {
578 int i, n;
579
580 for(i = 0; i < len-1; i += 2)
581 {
582 n = SRY_GET_SHORT(data + i) & 0xffff;
583 if(virtualPalette[n] != NULL)
584 {
585 free(virtualPalette[n]);
586 virtualPalette[n] = NULL;
587 }
588 }
589 }
590
sry_new_vram(uint8 * data,int len)591 static void sry_new_vram(uint8 *data, int len)
592 {
593 int i, n, width, height, c;
594
595 for(i = 0; i < len-6; i += 7)
596 {
597 n = SRY_GET_SHORT(data + i) & 0xffff;
598 width = SRY_GET_SHORT(data + i + 2) & 0xffff;
599 height = SRY_GET_SHORT(data + i + 4) & 0xffff;
600 c = data[6];
601 #ifdef SRY_DEBUG
602 printf("sherry: new vram[%d] %dx%d (t=%d)\n",
603 n, width, height, c);
604 #endif /* SRY_DEBUG */
605
606 if(virtualScreen[n] != NULL)
607 free_vscreen(virtualScreen[n]);
608 virtualScreen[n] = alloc_vscreen(width, height, c);
609 }
610 }
611
sry_free_vram(uint8 * data,int len)612 static void sry_free_vram(uint8 *data, int len)
613 {
614 int i, n;
615 for(i = 0; i < len-1; i += 2)
616 {
617 n = SRY_GET_SHORT(data + i) & 0xffff;
618 if(virtualScreen[n] != NULL)
619 {
620 free_vscreen(virtualScreen[n]);
621 virtualScreen[n] = NULL;
622 }
623 }
624 }
625
sry_pal_set(uint8 * data,int len)626 static void sry_pal_set(uint8 *data, int len)
627 {
628 int pg, i, p;
629 SherryPaletteEntry *entry;
630
631 pg = SRY_GET_SHORT(data) & 0xffff;
632 if(virtualPalette[pg] == NULL)
633 {
634 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
635 "WRD Sherry: virtual palette %d is not allocated", pg);
636 err_to_stop = 1;
637 return;
638 }
639 entry = virtualPalette[pg]->entry;
640 data += 2;
641 len -= 2;
642
643 #ifdef SRY_DEBUG
644 printf("set palette color of %d (n=%d)\n", pg, len / 4);
645 #endif /* SRY_DEBUG */
646
647 for(i = 0; i < len - 3; i += 4)
648 {
649 p = data[i];
650 entry[p].r = data[i + 1];
651 entry[p].g = data[i + 2];
652 entry[p].b = data[i + 3];
653 }
654 }
655
update_real_screen(int x,int y,int width,int height)656 static void update_real_screen(int x, int y, int width, int height)
657 {
658 if(!draw_ctl_flag)
659 return;
660 #if XSHM_SUPPORT
661 if(theRealScreen->shminfo.shmid != -1)
662 {
663 XShmPutImage(theDisplay, theWindow, theGC, theRealScreen->im,
664 x, y, x, y, width, height, False);
665 return;
666 }
667 #endif
668
669 XPutImage(theDisplay, theWindow, theGC, theRealScreen->im,
670 x, y, x, y, width, height);
671 }
672
updateScreen(int sx,int sy,int width,int height)673 static void updateScreen(int sx, int sy, int width, int height)
674 {
675 if(theClass == TrueColor)
676 {
677 XImage *im;
678 int x, y, c;
679 int units_per_line;
680 unsigned long pixels[MAX_COLORS];
681
682 for(c = 0; c < MAX_COLORS; c++)
683 pixels[c] = trueColorPixel(realPalette[c].r,
684 realPalette[c].g,
685 realPalette[c].b);
686
687 im = theRealScreen->im;
688 units_per_line = im->bytes_per_line / (im->bits_per_pixel / 8);
689
690 switch(im->bits_per_pixel)
691 {
692 #if 1
693 case 8:
694 for(y = 0; y < height; y++)
695 for(x = 0; x < width; x++)
696 {
697 c = pseudoImage[(sy + y) * REAL_SCREEN_SIZE_X + sx + x];
698 im->data[(sy + y) * units_per_line + sx + x] = pixels[c];
699 }
700 break;
701 case 16:
702 for(y = 0; y < height; y++)
703 for(x = 0; x < width; x++)
704 {
705 c = pseudoImage[(sy + y) * REAL_SCREEN_SIZE_X + sx + x];
706 ((uint16 *)im->data)[(sy + y) * units_per_line + sx + x]
707 = pixels[c];
708 }
709 break;
710 case 32:
711 for(y = 0; y < height; y++)
712 for(x = 0; x < width; x++)
713 {
714 c = pseudoImage[(sy + y) * REAL_SCREEN_SIZE_X + sx + x];
715 ((uint32 *)im->data)[(sy + y) * units_per_line + sx + x]
716 = pixels[c];
717 }
718 break;
719 #endif
720 default: /* Generic routine */
721 for(y = 0; y < height; y++)
722 for(x = 0; x < width; x++)
723 {
724 c = pseudoImage[(sy + y) * REAL_SCREEN_SIZE_X + sx + x];
725 XPutPixel(theRealScreen->im, sx + x, sy + y, pixels[c]);
726 }
727 break;
728 }
729 }
730
731 update_real_screen(sx, sy, width, height);
732 isRealScreenChanged = 0;
733 }
734
updatePalette(void)735 static void updatePalette(void)
736 {
737 int i;
738 XColor xc[256];
739
740 if(theClass != TrueColor)
741 {
742 for(i = 0; i < MAX_COLORS; i++)
743 {
744 xc[i].pixel = palette2Pixel[i];
745 xc[i].red = realPalette[i].r * 257;
746 xc[i].green = realPalette[i].g * 257;
747 xc[i].blue = realPalette[i].b * 257;
748 xc[i].flags = DoRed | DoGreen | DoBlue;
749 }
750 XStoreColors(theDisplay, theColormap, xc, MAX_COLORS);
751 }
752 else /* True color */
753 {
754 updateScreen(0, 0, REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y);
755 isRealScreenChanged = 0;
756 }
757 isRealPaletteChanged = 0;
758 }
759
760
sry_pal_v2r(uint8 * data)761 static void sry_pal_v2r(uint8 *data)
762 {
763 int n;
764 n = SRY_GET_SHORT(data) & 0xffff;
765
766 #ifdef SRY_DEBUG
767 printf("Transfer palette %d\n", n);
768 #endif /* SRY_DEBUG */
769
770 if(virtualPalette[n] == NULL)
771 {
772 virtualPalette[n] =
773 (SherryPalette *)safe_malloc(sizeof(SherryPalette));
774 memset(virtualPalette[n], 0, sizeof(SherryPalette));
775 }
776
777 memcpy(realPalette, virtualPalette[n]->entry, sizeof(realPalette));
778 isRealPaletteChanged = 1;
779 currentPalette = n;
780 }
781
png_read_func(png_structp png_ptr,char * buff,size_t n)782 static void png_read_func(png_structp png_ptr, char *buff, size_t n)
783 {
784 struct timidity_file *tf = png_get_io_ptr(png_ptr);
785 tf_read(buff, 1, n, tf);
786 }
787
788 #define PNG_BYTES_TO_CHECK 8
789 #define MAX_SCREEN_COLORS 256
sry_load_png(uint8 * data)790 static void sry_load_png(uint8 *data)
791 {
792 int i;
793 int x, y;
794 int screen, vpalette;
795 png_structp pngPtr;
796 png_infop infoPtr;
797 png_infop endInfo;
798 VirtualScreen *scr;
799 SherryPaletteEntry *entry;
800
801 char *filename;
802 struct timidity_file *tf;
803 char sig[PNG_BYTES_TO_CHECK];
804
805 png_uint_32 width, height;
806 int bitDepth, colorType, interlaceType, compressionType, filterType;
807
808 int numPalette;
809 png_colorp palette;
810 png_uint_16p hist;
811 png_bytep *rowPointers;
812 png_uint_32 rowbytes;
813 png_bytep trans;
814 int transParent;
815 int numTrans;
816 png_color_16p transValues;
817
818 numPalette = -1;
819 memset(&palette, 0, sizeof(palette));
820 hist = NULL;
821 rowbytes = 0;
822 rowPointers = NULL;
823 trans = NULL;
824 numTrans = 0;
825 transValues = NULL;
826
827 screen = SRY_GET_SHORT(data) & 0xffff;
828 vpalette = SRY_GET_SHORT(data + 2) & 0xffff;
829 filename = (char *)data + 4;
830
831 #ifdef SRY_DEBUG
832 printf("Load png: %s: scr=%d pal=%d\n", filename, screen, vpalette);
833 #endif /* SRY_DEBUG */
834
835 if((tf = wrd_open_file(filename)) == NULL)
836 {
837 err_to_stop = 1;
838 return;
839 }
840 if(tf_read(sig, 1, sizeof(sig), tf) != sizeof(sig))
841 {
842 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
843 "WRD Sherry: %s is too short to be png format.", filename);
844 err_to_stop = 1;
845 return;
846 }
847 if(png_sig_cmp((unsigned char*)sig, 0, sizeof(sig)))
848 {
849 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not a png file", filename);
850 err_to_stop = 1;
851 return;
852 }
853
854
855 pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
856 NULL, NULL, NULL);
857 infoPtr = png_create_info_struct(pngPtr);
858 endInfo = png_create_info_struct(pngPtr);
859
860 png_set_read_fn(pngPtr, (void *)tf, (png_rw_ptr)png_read_func);
861 png_set_sig_bytes(pngPtr, sizeof(sig));
862 png_read_info(pngPtr, infoPtr);
863
864 /* get info */
865 png_get_IHDR(pngPtr, infoPtr, &width, &height,
866 &bitDepth, &colorType,
867 &interlaceType, &compressionType, &filterType);
868
869 /* transformation */
870 /* contert to 256 palette */
871 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
872 png_set_expand(pngPtr);
873 if(bitDepth == 16)
874 png_set_strip_16(pngPtr);
875 if(bitDepth < 8)
876 png_set_packing(pngPtr);
877 if(colorType == PNG_COLOR_TYPE_GRAY ||
878 colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
879 png_set_gray_to_rgb(pngPtr);
880
881 #if 0
882 double screenGamma;
883 const char* const gammaStr = getenv ("SCREEN_GAMMA");
884 if (gammaStr != NULL)
885 {
886 screenGamma = atof (gammaStr);
887 }
888 else
889 {
890 screenGamma = 2.2;
891 /*
892 screenGamms = 2.0;
893 screenGamms = 1.7;
894 screenGamms = 1.0;
895 */
896 }
897
898 if (png_get_gAMA (pngPtr, infoPtr, &gamma))
899 png_set_gamma (pngPtr, screenGamma, gamma);
900 else
901 png_set_gamma (pngPtr, screenGamma, 0.50);
902 #endif
903
904 if(png_get_valid(pngPtr, infoPtr, PNG_INFO_PLTE))
905 {
906 png_get_PLTE(pngPtr, infoPtr, &palette, &numPalette);
907 if(numPalette > MAX_SCREEN_COLORS)
908 {
909 if(png_get_valid(pngPtr, infoPtr, PNG_INFO_hIST))
910 png_get_hIST(pngPtr, infoPtr, &hist);
911 #if PNG_LIBPNG_VER >= 10402
912 png_set_quantize(pngPtr, palette,
913 #else
914 png_set_dither(pngPtr, palette,
915 #endif
916 numPalette, MAX_SCREEN_COLORS, hist, 1);
917 }
918 }
919 else
920 {
921 /* XXX */
922 /* NOTE 6*7*6 = 252 */
923 /* 6*7*6 = 5*7*6 + 6*6 + 6 */
924 png_color stdColorCube[6*7*6];
925 png_byte r, g, b;
926
927 for(r = 0; r < 6; r++)
928 {
929 for(g = 0; g < 7; g++)
930 {
931 for(b = 0; b < 6; b++)
932 {
933 png_byte index = r*7*6+g*6+b;
934 stdColorCube[index].red = r;
935 stdColorCube[index].green = g;
936 stdColorCube[index].blue = b;
937 }
938 }
939 }
940 #if PNG_LIBPNG_VER >= 10402
941 png_set_quantize(pngPtr, stdColorCube,
942 #else
943 png_set_dither(pngPtr, stdColorCube,
944 #endif
945 6*7*6, MAX_SCREEN_COLORS,
946 NULL, 1);
947 png_get_PLTE(pngPtr, infoPtr, &palette, &numPalette);
948 }
949
950 if(png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
951 png_get_tRNS(pngPtr, infoPtr, &trans, &numTrans, &transValues);
952
953 png_read_update_info(pngPtr, infoPtr);
954
955 rowbytes = png_get_rowbytes(pngPtr, infoPtr);
956 /* rowbytes == width */
957 rowPointers = (png_bytep *)safe_malloc(height * sizeof(png_bytep));
958 rowPointers[0] = (png_byte *)safe_malloc(rowbytes * height *
959 sizeof(png_byte));
960 for(i = 1; i < height; i++)
961 rowPointers[i] = rowPointers[0] + i * rowbytes;
962
963 png_read_image(pngPtr, rowPointers);
964 png_read_end(pngPtr, endInfo);
965
966 if(trans == NULL || numTrans == 0)
967 transParent = 0;
968 else
969 transParent = trans[0] & 0xff;
970
971 scr = virtualScreen[screen];
972 if(scr != NULL && (scr->width != width || scr->height != height))
973 {
974 free_vscreen(scr);
975 scr = NULL;
976 }
977 if(scr == NULL)
978 scr = virtualScreen[screen] =
979 alloc_vscreen(width, height*2, transParent);
980 else
981 scr->transParent = transParent;
982
983 if(virtualPalette[vpalette] == NULL)
984 {
985 virtualPalette[vpalette] =
986 (SherryPalette *)safe_malloc(sizeof(SherryPalette));
987 memset(virtualPalette[vpalette], 0, sizeof(SherryPalette));
988 }
989
990 entry = virtualPalette[vpalette]->entry;
991 for(i = 0; i < numPalette; i++)
992 {
993 entry[i].r = palette[i].red;
994 entry[i].g = palette[i].green;
995 entry[i].b = palette[i].blue;
996 }
997
998 for(y = 0; y < height; y++)
999 for(x = 0; x < width; x++)
1000 VSCREEN_PIXEL(scr, x, y) = rowPointers[y][x];
1001
1002 free(rowPointers[0]);
1003 free(rowPointers);
1004 png_destroy_read_struct(&pngPtr, &infoPtr, &endInfo);
1005 close_file(tf);
1006 #ifdef SRY_DEBUG
1007 printf("Load png ok: width=%d height=%d\n", width, height);
1008 #endif /* SRY_DEBUG */
1009 }
1010
sry_trans_all(uint8 * data)1011 static void sry_trans_all(uint8 *data)
1012 {
1013 int screen, x, y;
1014 int sx, sy;
1015 VirtualScreen *scr;
1016 XImage *im;
1017
1018 screen = SRY_GET_SHORT(data + 0) & 0xffff;
1019 sx = SRY_GET_SHORT(data + 2) & 0xffff;
1020 sy = SRY_GET_SHORT(data + 4) & 0xffff;
1021 im = theRealScreen->im;
1022 scr = virtualScreen[screen];
1023
1024 #ifdef SRY_DEBUG
1025 printf("Trans all: %d:(%d,%d)\n", screen, sx, sy);
1026 #endif /* SRY_DEBUG */
1027
1028 if(!check_range(scr, sx, sy,
1029 sx + REAL_SCREEN_SIZE_X - 1, sy + REAL_SCREEN_SIZE_Y - 1))
1030 return;
1031
1032 if(theClass != TrueColor)
1033 {
1034 for(y = 0; y < REAL_SCREEN_SIZE_Y; y++)
1035 for(x = 0; x < REAL_SCREEN_SIZE_X; x++)
1036 XPutPixel(im, x, y, VSCREEN_PIXEL(scr, sx + x, sy + y));
1037 }
1038 else /* TrueColor */
1039 {
1040 for(y = 0; y < REAL_SCREEN_SIZE_Y; y++)
1041 memcpy(pseudoImage + y * REAL_SCREEN_SIZE_X,
1042 scr->data + (sy + y) * scr->width + sx,
1043 REAL_SCREEN_SIZE_X);
1044 }
1045
1046 isRealScreenChanged = 1;
1047 updateClipX1 = 0;
1048 updateClipY1 = 0;
1049 updateClipX2 = REAL_SCREEN_SIZE_X-1;
1050 updateClipY2 = REAL_SCREEN_SIZE_Y-1;
1051 }
1052
sry_trans_partial_real(uint8 * data)1053 static void sry_trans_partial_real(uint8 *data)
1054 {
1055 int screen, sx, sy, tx, ty, w, h, x, y;
1056 int x2, y2;
1057 VirtualScreen *scr;
1058 XImage *im;
1059
1060 screen = SRY_GET_SHORT(data + 0) & 0xffff;
1061 sx = SRY_GET_SHORT(data + 2) & 0xffff;
1062 sy = SRY_GET_SHORT(data + 4) & 0xffff;
1063 tx = SRY_GET_SHORT(data + 6) & 0xffff;
1064 ty = SRY_GET_SHORT(data + 8) & 0xffff;
1065 w = SRY_GET_SHORT(data +10) & 0xffff;
1066 h = SRY_GET_SHORT(data +12) & 0xffff;
1067 x2 = tx + w - 1;
1068 if(x2 >= REAL_SCREEN_SIZE_X)
1069 {
1070 x2 = REAL_SCREEN_SIZE_X - 1;
1071 w = x2 - tx + 1;
1072 }
1073 y2 = ty + h - 1;
1074 if(y2 >= REAL_SCREEN_SIZE_Y)
1075 {
1076 y2 = REAL_SCREEN_SIZE_Y - 1;
1077 h = y2 - ty + 1;
1078 }
1079
1080 #ifdef SRY_DEBUG
1081 printf("Trans partial: %d:(%d,%d) (%d,%d) %dx%d\n",
1082 screen, sx, sy, tx, ty, w, h);
1083 #endif /* SRY_DEBUG */
1084
1085 im = theRealScreen->im;
1086 scr = virtualScreen[screen];
1087
1088 if(theClass != TrueColor)
1089 {
1090 for(y = 0; y < h; y++)
1091 for(x = 0; x < w; x++)
1092 XPutPixel(im, tx + x, ty + y,
1093 VSCREEN_PIXEL(scr, sx + x, sy + y));
1094 }
1095 else
1096 {
1097 for(y = 0; y < h; y++)
1098 {
1099 memcpy(pseudoImage + (ty + y) * REAL_SCREEN_SIZE_X + tx,
1100 scr->data + (sy + y) * scr->width + sx,
1101 w);
1102 }
1103 }
1104
1105 if(isRealScreenChanged)
1106 {
1107 /*???*/
1108 x_sry_update();
1109 }
1110 updateClipX1 = tx;
1111 updateClipY1 = ty;
1112 updateClipX2 = x2;
1113 updateClipY2 = y2;
1114 isRealScreenChanged = 1;
1115 }
1116
get_tmp_screen(int width_require,int height_require)1117 static VirtualScreen *get_tmp_screen(int width_require,
1118 int height_require)
1119 {
1120 if(tmpScreen == NULL)
1121 {
1122 if(width_require < REAL_SCREEN_SIZE_X)
1123 width_require = REAL_SCREEN_SIZE_X;
1124 if(height_require < REAL_SCREEN_SIZE_Y)
1125 height_require = REAL_SCREEN_SIZE_Y;
1126 return tmpScreen = alloc_vscreen(width_require, height_require, 0);
1127 }
1128 if(tmpScreen->width * tmpScreen->height >= width_require * height_require)
1129 {
1130 tmpScreen->width = width_require;
1131 tmpScreen->height = height_require;
1132 return tmpScreen;
1133 }
1134 if(tmpScreen)
1135 free_vscreen(tmpScreen);
1136 return tmpScreen = alloc_vscreen(width_require, height_require, 0);
1137 }
1138
normalize_rect(int * x1,int * y1,int * x2,int * y2)1139 static void normalize_rect(int *x1, int *y1, int *x2, int *y2)
1140 {
1141 int w, h, x0, y0;
1142
1143 w = *x2 - *x1;
1144 if(w >= 0)
1145 x0 = *x1;
1146 else
1147 {
1148 w = -w;
1149 x0 = *x2;
1150 }
1151
1152 h = *y2 - *y1;
1153 if(h >= 0)
1154 y0 = *y1;
1155 else
1156 {
1157 h = -h;
1158 y0 = *y2;
1159 }
1160
1161 *x1 = x0;
1162 *y1 = y0;
1163 *x2 = x0 + w;
1164 *y2 = y0 + h;
1165 }
1166
check_range(VirtualScreen * scr,int x1,int y1,int x2,int y2)1167 static int check_range(VirtualScreen *scr,
1168 int x1, int y1, int x2, int y2)
1169 {
1170 if(x1 < 0 ||
1171 y1 < 0 ||
1172 x2 >= scr->width ||
1173 y2 >= scr->height ||
1174 x1 > x2 ||
1175 y1 > y2)
1176 {
1177 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1178 "Sherry WRD: Out of range: (%d,%d)-(%d,%d)"
1179 " > %dx%d, stop sherring",
1180 x1, y1, x2, y2, scr->width, scr->height);
1181 err_to_stop = 1;
1182 return 0;
1183 }
1184 return 1;
1185 }
1186
virtual_screen(int scr)1187 static VirtualScreen *virtual_screen(int scr)
1188 {
1189 if(virtualScreen[scr] == NULL)
1190 {
1191 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1192 "Sherry WRD: screen %d is not allocated, stop sherring",
1193 scr);
1194 err_to_stop = 1;
1195 return NULL;
1196 }
1197 return virtualScreen[scr];
1198 }
1199
copy_vscreen_area(VirtualScreen * src,VirtualScreen * dest,int src_x1,int src_y1,int src_x2,int src_y2,int dest_x,int dest_y,int mask,int trans)1200 static void copy_vscreen_area(VirtualScreen *src,
1201 VirtualScreen *dest,
1202 int src_x1,
1203 int src_y1,
1204 int src_x2,
1205 int src_y2,
1206 int dest_x,
1207 int dest_y,
1208 int mask,
1209 int trans)
1210 {
1211 int x, y, sw, dw;
1212 uint8 *source, *target;
1213 int ww, hh;
1214
1215 sw = src->width;
1216 dw = dest->width;
1217 source = src->data;
1218 target = dest->data;
1219 ww = src_x2 - src_x1 + 1;
1220 hh = src_y2 - src_y1 + 1;
1221
1222 if(mask == 0xff && !trans)
1223 {
1224 for(y = 0; y < hh; y++)
1225 {
1226 memcpy(target + (dest_y + y) * dw + dest_x,
1227 source + (src_y1 + y) * sw + src_x1, ww);
1228 }
1229 }
1230 else
1231 {
1232 int p, q, i;
1233 int skip_color;
1234
1235 skip_color = trans? src->transParent : -1;
1236 for(y = 0; y < hh; y++)
1237 {
1238 for(x = 0; x < ww; x++)
1239 {
1240 p = source[(src_y1 + y) * sw + src_x1 + x];
1241 if(p == skip_color)
1242 continue;
1243 i = (dest_y + y) * dw + dest_x + x;
1244 q = target[i];
1245 target[i] = ROP3_CA0749(mask, p, q);
1246 }
1247 }
1248 }
1249 }
1250
sry_trans_partial(uint8 * data)1251 static void sry_trans_partial(uint8 *data)
1252 {
1253 VirtualScreen *src, *dest;
1254 int from, to;
1255 int x1, y1, x2, y2, tx, ty;
1256 int mask, trans;
1257
1258 from = SRY_GET_SHORT(data + 0) & 0xffff;
1259 to = SRY_GET_SHORT(data + 2) & 0xffff;
1260 mask = data[4];
1261 trans = data[5];
1262 x1 = SRY_GET_SHORT(data + 6) & 0xffff;
1263 y1 = SRY_GET_SHORT(data + 8) & 0xffff;
1264 x2 = SRY_GET_SHORT(data +10) & 0xffff;
1265 y2 = SRY_GET_SHORT(data +12) & 0xffff;
1266 tx = SRY_GET_SHORT(data +14) & 0xffff;
1267 ty = SRY_GET_SHORT(data +16) & 0xffff;
1268
1269 if((src = virtual_screen(from)) == NULL)
1270 return;
1271 if((dest = virtual_screen(to)) == NULL)
1272 return;
1273
1274 #ifdef SRY_DEBUG
1275 printf("Screen copy: %d:(%d,%d)-(%d,%d) -> %d:(%d,%d) mask=0x%02x trans=%d\n",
1276 from, x1, y1, x2, y2, to, tx, ty,
1277 mask, trans);
1278 #endif /* SRY_DEBUG */
1279
1280 normalize_rect(&x1, &y1, &x2, &y2);
1281 if(!check_range(src, x1, y1, x2, y2))
1282 return;
1283 if(!check_range(dest, tx, ty, tx + x2 - x1, ty + y2 - y1))
1284 return;
1285
1286 if(src == dest)
1287 {
1288 VirtualScreen *tmp;
1289 tmp = get_tmp_screen(x2 + 1, y2 + 1);
1290 tmp->transParent = src->transParent;
1291 copy_vscreen_area(src, tmp, x1, y1, x2, y2, x1, y1, 0xff, 0);
1292 src = tmp;
1293 }
1294
1295 copy_vscreen_area(src, dest, x1, y1, x2, y2, tx, ty, mask, trans);
1296 }
1297
sry_trans_partial_mask(uint8 * data)1298 static void sry_trans_partial_mask(uint8 *data)
1299 {
1300 int from, to;
1301 int planeMask, transparencyFlag;
1302 int x1, y1, x2, y2, toX, toY;
1303 int maskX, maskY;
1304 uint8 *maskData;
1305 VirtualScreen *src, *dest;
1306 int x, y, width, height;
1307 int mx, my;
1308 int bytesPerLine;
1309 int srcP, dstP;
1310
1311 from = SRY_GET_SHORT(data + 0) & 0xffff;
1312 to = SRY_GET_SHORT(data + 2) & 0xffff;
1313 planeMask = data[4];
1314 transparencyFlag = data[5];
1315 x1 = SRY_GET_SHORT(data + 6) & 0xffff;
1316 y1 = SRY_GET_SHORT(data + 8) & 0xffff;
1317 x2 = SRY_GET_SHORT(data +10) & 0xffff;
1318 y2 = SRY_GET_SHORT(data +12) & 0xffff;
1319 toX = SRY_GET_SHORT(data +14) & 0xffff;
1320 toY = SRY_GET_SHORT(data +16) & 0xffff;
1321 maskX = data[18];
1322 maskY = data[19];
1323 maskData = data + 20;
1324
1325 width = x2 - x1 + 1;
1326 height = y2 - y1 + 1;
1327
1328 if((src = virtual_screen(from)) == NULL)
1329 return;
1330 if((dest = virtual_screen(to)) == NULL)
1331 return;
1332 normalize_rect(&x1, &y1, &x2, &y2);
1333 if(!check_range(src, x1, y1, x2, y2))
1334 return;
1335 if(!check_range(dest, toX, toY, toX + x2 - x1, toY + y2 - y1))
1336 return;
1337
1338 if(src == dest)
1339 {
1340 VirtualScreen *tmp;
1341 tmp = get_tmp_screen(x2 + 1, y2 + 1);
1342 tmp->transParent = src->transParent;
1343 copy_vscreen_area(src, tmp, x1, y1, x2, y2, x1, y1, 0xff, 0);
1344 src = tmp;
1345 }
1346
1347 bytesPerLine = maskX;
1348 bytesPerLine = ((bytesPerLine + 7) & ~7); /* round up to 8 */
1349 bytesPerLine /= 8;
1350
1351 my = y1 % maskY;
1352 for(y = 0; y < height; y++, my++)
1353 {
1354 if(my == maskY)
1355 my = 0;
1356 mx = x1 % maskX;
1357 for(x = 0; x < width; x++, mx++)
1358 {
1359 if(mx == maskX)
1360 mx = 0;
1361 if(maskData[my * bytesPerLine + mx / 8] & (0x80 >> (mx%8)))
1362 {
1363 srcP = VSCREEN_PIXEL(src, x1 + x, y1 + y);
1364 if(!transparencyFlag || srcP != src->transParent)
1365 {
1366 dstP = VSCREEN_PIXEL(dest, toX + x, toY + y);
1367 VSCREEN_PIXEL(dest, toX + x, toY + y) =
1368 ROP3_CA0749(planeMask, srcP, dstP);
1369 }
1370 }
1371 }
1372 }
1373 }
1374
1375
sry_draw_box(uint8 * data)1376 static void sry_draw_box(uint8 *data)
1377 {
1378 int screen;
1379 int mask;
1380 int x1, y1, x2, y2, x, y;
1381 int color;
1382 VirtualScreen *v;
1383
1384 screen = SRY_GET_SHORT(data + 0) & 0xffff;
1385 mask = data[2];
1386 x1 = SRY_GET_SHORT(data + 3) & 0xffff;
1387 y1 = SRY_GET_SHORT(data + 5) & 0xffff;
1388 x2 = SRY_GET_SHORT(data + 7) & 0xffff;
1389 y2 = SRY_GET_SHORT(data + 9) & 0xffff;
1390 color = data[11];
1391
1392 #ifdef SRY_DEBUG
1393 printf("Box %d 0x%02x (%d,%d)-(%d,%d)\n", screen, mask, x1, y1, x2, y2);
1394 #endif /* SRY_DEBUG */
1395
1396 if((v = virtual_screen(screen)) == NULL)
1397 return;
1398 normalize_rect(&x1, &y1, &x2, &y2);
1399 if(!check_range(v, x1, y1, x2, y2))
1400 return;
1401
1402 if(mask == 0xff)
1403 {
1404 for(y = y1; y <= y2; y++)
1405 memset(v->data + v->width * y + x1, color, x2 - x1 + 1);
1406 }
1407 else
1408 {
1409 int p;
1410 for(y = y1; y <= y2; y++)
1411 for(x = x1; x <= x2; x++)
1412 {
1413 int i;
1414 i = v->width * y + x;
1415 p = v->data[i];
1416 v->data[i] = ROP3_CA0749(mask, color, p);
1417 }
1418 }
1419 }
1420
vscreen_drawline(VirtualScreen * scr,int x1,int y1,int x2,int y2,int pixel,int mask)1421 static void vscreen_drawline(VirtualScreen* scr,
1422 int x1, int y1, int x2, int y2,
1423 int pixel, int mask)
1424 {
1425 int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag, idx;
1426
1427 if(scr == NULL)
1428 return;
1429
1430 if(x1 < 0 ||
1431 y1 < 0 ||
1432 x2 >= scr->width ||
1433 y2 >= scr->height)
1434 {
1435 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1436 "Sherry WRD: Out of range: (%d,%d)-(%d,%d)"
1437 " > %dx%d, stop sherring",
1438 x1, y1, x2, y2, scr->width, scr->height);
1439 err_to_stop = 1;
1440 return;
1441 }
1442
1443 dx = x2 - x1; if(dx < 0) dx = -dx; /* dx = |x2-x1| */
1444 dy = y2 - y1; if(dy < 0) dy = -dy; /* dy = |y2-y1| */
1445
1446 if(dy <= dx)
1447 {
1448 d = 2 * dy - dx;
1449 incr1 = 2 * dy;
1450 incr2 = 2 * (dy - dx);
1451 if(x1 > x2)
1452 {
1453 x = x2;
1454 y = y2;
1455 ydirflag = -1;
1456 xend = x1;
1457 }
1458 else
1459 {
1460 x = x1;
1461 y = y1;
1462 ydirflag = 1;
1463 xend = x2;
1464 }
1465
1466 idx = scr->width * y + x;
1467 scr->data[idx] = ROP3_CA0749(mask, pixel, scr->data[idx]);
1468 if((y2 - y1) * ydirflag > 0)
1469 {
1470 while(x < xend)
1471 {
1472 x++;
1473 if(d < 0)
1474 d += incr1;
1475 else
1476 {
1477 y++;
1478 d += incr2;
1479 }
1480 idx = scr->width * y + x;
1481 scr->data[idx] = ROP3_CA0749(mask, pixel, scr->data[idx]);
1482 }
1483 }
1484 else
1485 {
1486 while(x < xend)
1487 {
1488 x++;
1489 if(d < 0)
1490 d += incr1;
1491 else
1492 {
1493 y--;
1494 d += incr2;
1495 }
1496 idx = scr->width * y + x;
1497 scr->data[idx] = ROP3_CA0749(mask, pixel, scr->data[idx]);
1498 }
1499 }
1500 }
1501 else
1502 {
1503 d = 2 * dx - dy;
1504 incr1 = 2 * dx;
1505 incr2 = 2 * (dx - dy);
1506 if(y1 > y2)
1507 {
1508 y = y2;
1509 x = x2;
1510 yend = y1;
1511 xdirflag = -1;
1512 }
1513 else
1514 {
1515 y = y1;
1516 x = x1;
1517 yend = y2;
1518 xdirflag = 1;
1519 }
1520 idx = scr->width * y + x;
1521 scr->data[idx] = ROP3_CA0749(mask, pixel, scr->data[idx]);
1522 if((x2 - x1) * xdirflag > 0)
1523 {
1524 while(y < yend)
1525 {
1526 y++;
1527 if(d <0)
1528 d += incr1;
1529 else
1530 {
1531 x++;
1532 d += incr2;
1533 }
1534 idx = scr->width * y + x;
1535 scr->data[idx] = ROP3_CA0749(mask, pixel, scr->data[idx]);
1536 }
1537 }
1538 else
1539 {
1540 while(y < yend)
1541 {
1542 y++;
1543 if(d < 0)
1544 d += incr1;
1545 else
1546 {
1547 x--;
1548 d += incr2;
1549 }
1550 idx = scr->width * y + x;
1551 scr->data[idx] = ROP3_CA0749(mask, pixel, scr->data[idx]);
1552 }
1553 }
1554 }
1555 }
1556
sry_draw_vline(uint8 * data)1557 static void sry_draw_vline(uint8 *data)
1558 {
1559 int screen = SRY_GET_SHORT(data + 0) & 0xffff;
1560 int mask = data[2];
1561 int x1 = SRY_GET_SHORT(data + 3) & 0xffff;
1562 int y1 = SRY_GET_SHORT(data + 5) & 0xffff;
1563 int y2 = SRY_GET_SHORT(data + 7) & 0xffff;
1564 int color = data[9];
1565
1566 vscreen_drawline(virtual_screen(screen),
1567 x1, y1, x1, y2, color, mask);
1568 }
1569
sry_draw_hline(uint8 * data)1570 static void sry_draw_hline(uint8 *data)
1571 {
1572 int screen = SRY_GET_SHORT(data + 0) & 0xffff;
1573 int mask = data[2];
1574 int x1 = SRY_GET_SHORT(data + 3) & 0xffff;
1575 int x2 = SRY_GET_SHORT(data + 5) & 0xffff;
1576 int y1 = SRY_GET_SHORT(data + 7) & 0xffff;
1577 int color = data[9];
1578
1579 vscreen_drawline(virtual_screen(screen),
1580 x1, y1, x2, y1, color, mask);
1581 }
1582
sry_draw_line(uint8 * data)1583 static void sry_draw_line(uint8 *data)
1584 {
1585 int screen = SRY_GET_SHORT(data + 0) & 0xffff;
1586 int mask = data[2];
1587 int x1 = SRY_GET_SHORT(data + 3) & 0xffff;
1588 int y1 = SRY_GET_SHORT(data + 5) & 0xffff;
1589 int x2 = SRY_GET_SHORT(data + 7) & 0xffff;
1590 int y2 = SRY_GET_SHORT(data + 9) & 0xffff;
1591 int color = data[11];
1592
1593 vscreen_drawline(virtual_screen(screen),
1594 x1, y1, x2, y2, color, mask);
1595 }
1596
sry_pal_merge(uint8 * data)1597 static void sry_pal_merge(uint8 *data)
1598 {
1599 int Pal1, Pal2, PalResult;
1600 int Pal1in, Pal1bit, Pal1out;
1601 int Pal2in, Pal2bit, Pal2out;
1602 int Per1, Per2;
1603 int Pal1Mask, Pal2Mask, PalMask;
1604 int i;
1605 int i1, i2;
1606 SherryPaletteEntry *pal_in1, *pal_in2, *pal_res;
1607
1608 Pal1 = SRY_GET_SHORT(data + 0) & 0xffff;
1609 Pal2 = SRY_GET_SHORT(data + 2) & 0xffff;
1610 PalResult = SRY_GET_SHORT(data + 4) & 0xffff;
1611 Pal1in = data[6];
1612 Pal1bit = data[7];
1613 Pal1out = data[8];
1614 Pal2in = data[9];
1615 Pal2bit = data[10];
1616 Pal2out = data[11];
1617 Per1 = data[12];
1618 Per2 = data[13];
1619
1620 Pal1Mask = 0xff >> ( 8 - Pal1bit );
1621 Pal1Mask <<= Pal1out;
1622 Pal2Mask = 0xff >> ( 8 - Pal2bit );
1623 Pal2Mask <<= Pal2out;
1624 PalMask = Pal1Mask | Pal2Mask;
1625
1626 #ifdef SRY_DEBUG
1627 printf("palette merge %d(%d%%) %d(%d%%) => %d (mask=0x%x)\n",
1628 Pal1, Per1,
1629 Pal2, Per2,
1630 PalResult,
1631 PalMask);
1632 #endif /* SRY_DEBUG */
1633
1634 if(virtualPalette[Pal1] == NULL)
1635 {
1636 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1637 "Sherry WRD: palette %d is not allocated, stop sherring",
1638 Pal1);
1639 err_to_stop = 1;
1640 return;
1641 }
1642
1643 if(virtualPalette[Pal2] == NULL)
1644 {
1645 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1646 "Sherry WRD: palette %d is not allocated, stop sherring",
1647 Pal2);
1648 err_to_stop = 1;
1649 return;
1650 }
1651
1652 if(virtualPalette[PalResult] == NULL)
1653 {
1654 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1655 "Sherry WRD: palette %d is not allocated, stop sherring",
1656 PalResult);
1657 err_to_stop = 1;
1658 return;
1659 }
1660
1661 pal_in1 = virtualPalette[Pal1]->entry;
1662 pal_in2 = virtualPalette[Pal2]->entry;
1663 pal_res = virtualPalette[PalResult]->entry;
1664
1665 for(i = 0; i < MAX_COLORS; i++)
1666 {
1667 if((i & PalMask) == i)
1668 {
1669 int p;
1670
1671 i1 = (i & Pal1Mask) >> Pal1in;
1672 i2 = (i & Pal2Mask) >> Pal2in;
1673
1674 p = pal_in1[i1].r * Per1 / 100 + pal_in2[i2].r * Per2 / 100;
1675 if(p > 0xff) p = 0xff;
1676 pal_res[i].r = p;
1677
1678 p = pal_in1[i1].g * Per1 / 100 + pal_in2[i2].g * Per2 / 100;
1679 if(p > 0xff) p = 0xff;
1680 pal_res[i].g = p;
1681
1682 p = pal_in1[i1].b * Per1 / 100 + pal_in2[i2].b * Per2 / 100;
1683 if(p > 0xff) p = 0xff;
1684 pal_res[i].b = p;
1685 }
1686 }
1687 }
1688
sry_pal_copy(uint8 * data)1689 static void sry_pal_copy(uint8 *data)
1690 {
1691 int pal1, pal2;
1692
1693 pal1 = SRY_GET_SHORT(data + 0) & 0xffff;
1694 pal2 = SRY_GET_SHORT(data + 2) & 0xffff;
1695
1696 #ifdef SRY_DEBUG
1697 printf("Copy palette %d->%d\n", pal1, pal2);
1698 #endif /* SRY_DEBUG */
1699
1700 if(virtualPalette[pal1] == NULL)
1701 {
1702 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1703 "Sherry WRD: palette %d is not allocated, stop sherring",
1704 pal1);
1705 err_to_stop = 1;
1706 return;
1707 }
1708
1709 if(virtualPalette[pal2] == NULL)
1710 virtualPalette[pal2] =
1711 (SherryPalette *)safe_malloc(sizeof(SherryPalette));
1712 memcpy(virtualPalette[pal2], virtualPalette[pal1], sizeof(SherryPalette));
1713 }
1714
sry_text(uint8 * data)1715 static void sry_text(uint8 *data)
1716 {
1717 int screen, mask, mode, bg, fg, tx, ty;
1718 char *str;
1719 int len, advance;
1720 VirtualScreen *scr;
1721
1722 screen = SRY_GET_SHORT(data + 0);
1723 mask = data[2];
1724 mode = data[3];
1725 fg = data[4];
1726 bg = data[5];
1727 tx = SRY_GET_SHORT(data + 6);
1728 ty = SRY_GET_SHORT(data + 8);
1729 str = (char *)data + 10;
1730 len = strlen(str);
1731
1732 if(len == 0)
1733 return;
1734
1735 #ifdef SRY_DEBUG
1736 printf("%d 0x%02x %d %d %d (%d,%d)\n%s\n",
1737 screen, mask, mode, fg, bg, tx, ty, str);
1738 #endif /* SRY_DEBUG */
1739
1740 if((scr = virtual_screen(screen)) == NULL)
1741 return;
1742
1743 if(!check_range(scr,
1744 tx, ty, tx + CHAR_WIDTH1 * len - 1, ty + CHAR_HEIGHT - 1))
1745 return;
1746
1747 while((advance = bitmap_drawimage(imageBitmap, str, len)) > 0)
1748 {
1749 int width, bx, by, p;
1750 width = advance * CHAR_WIDTH1;
1751
1752 for(by = 0; by < CHAR_HEIGHT; by++)
1753 {
1754 for(bx = 0; bx < width; bx++)
1755 {
1756 if(XGetPixel(imageBitmap->im, bx, by))
1757 {
1758 if(mode & 1)
1759 {
1760 p = VSCREEN_PIXEL(scr, tx + bx, ty + by);
1761 VSCREEN_PIXEL(scr, tx + bx, ty + by) =
1762 ROP3_CA0749(mask, fg, p);
1763 }
1764 }
1765 else
1766 {
1767 if(mode & 2)
1768 {
1769 p = VSCREEN_PIXEL(scr, tx + bx, ty + by);
1770 VSCREEN_PIXEL(scr, tx + bx, ty + by) =
1771 ROP3_CA0749(mask, bg, p);
1772 }
1773 }
1774 }
1775 }
1776
1777 str += advance;
1778 len -= advance;
1779 tx += advance * CHAR_WIDTH1;
1780 }
1781 }
1782
x_sry_clear(void)1783 void x_sry_clear(void)
1784 {
1785 int i;
1786
1787 if(theDisplay == NULL)
1788 return;
1789
1790 isRealPaletteChanged = 0;
1791 isRealScreenChanged = 0;
1792 err_to_stop = 0;
1793
1794 init_palette();
1795
1796 XSetWindowBackground(theDisplay, theWindow, basePixel);
1797 XClearWindow(theDisplay, theWindow);
1798
1799 clear_image_pixmap(theRealScreen, basePixel);
1800
1801 for(i = 0; i < MAX_VIRTUAL_SCREENS; i++)
1802 if(virtualScreen[i] != NULL)
1803 {
1804 free_vscreen(virtualScreen[i]);
1805 virtualScreen[i] = NULL;
1806 }
1807 if(tmpScreen)
1808 {
1809 free(tmpScreen);
1810 tmpScreen = NULL;
1811 }
1812
1813 for(i = 0; i < MAX_VIRTUAL_PALETTES; i++)
1814 if(virtualPalette[i] != NULL)
1815 {
1816 free(virtualPalette[i]);
1817 virtualPalette[i] = NULL;
1818 }
1819 memset(realPalette, 0, sizeof(realPalette));
1820 if(theClass == TrueColor)
1821 memset(pseudoImage, 0, REAL_SCREEN_SIZE_X * REAL_SCREEN_SIZE_Y);
1822 }
1823
1824
1825 #ifdef SRY_DEBUG
print_command(uint8 * data,int len)1826 static void print_command(uint8 *data, int len)
1827 {
1828 int i;
1829 printf("sherry:");
1830 for(i = 0; i < len; i++)
1831 {
1832 printf(" 0x%02x", data[i]);
1833 if(i >= 28)
1834 {
1835 printf("...");
1836 break;
1837 }
1838 }
1839 printf("\n");
1840 fflush(stdout);
1841 }
1842 #endif /* SRY_DEBUG */
1843
x_sry_wrdt_apply(uint8 * data,int len)1844 void x_sry_wrdt_apply(uint8 *data, int len)
1845 {
1846 int op, skip_bit;
1847
1848 if(err_to_stop || theDisplay == NULL)
1849 return;
1850
1851 #ifdef SRY_DEBUG
1852 print_command(data, len);
1853 #endif /* SRY_DEBUG */
1854
1855 op = *data++;
1856 len--;
1857
1858 skip_bit = op & 0x80;
1859 if(skip_bit && aq_filled_ratio() < 0.2)
1860 return;
1861 op &= 0x7F;
1862
1863 switch(op)
1864 {
1865 case 0x00: /* DataEnd */
1866 break;
1867 case 0x01:
1868 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "sherry start");
1869 wrd_init_path();
1870 x_sry_clear();
1871 break;
1872 case 0x21:
1873 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "new pal 0x21");
1874 sry_new_vpal(data, len);
1875 break;
1876 case 0x22:
1877 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "free pal 0x22");
1878 sry_free_vpal(data, len);
1879 break;
1880 case 0x25:
1881 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "new vram 0x25");
1882 sry_new_vram(data, len);
1883 break;
1884 case 0x26:
1885 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "free vram 0x26");
1886 sry_free_vram(data, len);
1887 break;
1888 case 0x27:
1889 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "load PNG 0x27");
1890 sry_load_png(data);
1891 break;
1892 case 0x31:
1893 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
1894 "palette trans 0x31 (%d)", SRY_GET_SHORT(data));
1895 sry_pal_v2r(data);
1896 break;
1897 case 0x35:
1898 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
1899 "image copy 0x35 (%d)", SRY_GET_SHORT(data));
1900 sry_trans_all(data);
1901 break;
1902 case 0x36:
1903 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
1904 "image copy 0x36 (%d)", SRY_GET_SHORT(data));
1905 sry_trans_partial_real(data);
1906 break;
1907 case 0x41:
1908 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "set pal 0x41");
1909 sry_pal_set(data, len);
1910 break;
1911 case 0x42:
1912 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "pal merge 0x42");
1913 sry_pal_merge(data);
1914 break;
1915 case 0x43:
1916 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "pal copy 0x43");
1917 sry_pal_copy(data);
1918 break;
1919 case 0x51:
1920 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "text 0x51");
1921 sry_text(data);
1922 break;
1923 case 0x52:
1924 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "draw box 0x52");
1925 sry_draw_box(data);
1926 break;
1927 case 0x53:
1928 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "draw line 0x53");
1929 sry_draw_vline(data);
1930 break;
1931 case 0x54:
1932 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "draw line 0x54");
1933 sry_draw_hline(data);
1934 break;
1935 case 0x55:
1936 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "draw line 0x55");
1937 sry_draw_line(data);
1938 break;
1939 case 0x61:
1940 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "image copy 0x61");
1941 sry_trans_partial(data);
1942 break;
1943 case 0x62:
1944 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "image copy 0x62");
1945 sry_trans_partial_mask(data);
1946 break;
1947 case 0x10:
1948 case 0x11:
1949 case 0x12:
1950 case 0x13:
1951 case 0x14:
1952 case 0x15:
1953 case 0x16:
1954 case 0x17:
1955 case 0x18:
1956 case 0x19:
1957 case 0x1a:
1958 case 0x1b:
1959 case 0x1c:
1960 case 0x1d:
1961 case 0x1e:
1962 case 0x1f:
1963 case 0x20:
1964 case 0x71:
1965 case 0x72:
1966 case 0x7f:
1967 ctl->cmsg(CMSG_WARNING, VERB_DEBUG,
1968 "Sherry WRD 0x%x: not supported, ignore", op);
1969 break;
1970
1971 default:
1972 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1973 "Sherry WRD 0x%x: not defined, stop sherring", op);
1974 err_to_stop = 1;
1975 break;
1976 }
1977 }
1978
x_sry_redraw_ctl(int flag)1979 void x_sry_redraw_ctl(int flag)
1980 {
1981 draw_ctl_flag = flag;
1982 if(draw_ctl_flag)
1983 update_real_screen(0, 0, REAL_SCREEN_SIZE_X, REAL_SCREEN_SIZE_Y);
1984 }
1985
x_sry_update(void)1986 void x_sry_update(void)
1987 {
1988 if(err_to_stop)
1989 return;
1990
1991 #ifdef SRY_DEBUG
1992 puts("Update pallete & screen");
1993 #endif /* SRY_DEBUG */
1994
1995 if(!isRealPaletteChanged && !isRealScreenChanged)
1996 return;
1997 if(isRealPaletteChanged)
1998 updatePalette();
1999 if(isRealScreenChanged)
2000 updateScreen(updateClipX1, updateClipY1,
2001 updateClipX2 - updateClipX1 + 1,
2002 updateClipY2 - updateClipY1 + 1);
2003 XSync(theDisplay, False);
2004 }
2005
2006
2007 /**** ImagePixmap interfaces ****/
create_image_pixmap(int width,int height,int depth)2008 static ImagePixmap *create_image_pixmap(int width, int height, int depth)
2009 {
2010 ImagePixmap *ip;
2011
2012 ip = (ImagePixmap *)safe_malloc(sizeof(ImagePixmap));
2013 ip->pm = XCreatePixmap(theDisplay, theWindow, width, height, depth);
2014 ip->im = XGetImage(theDisplay, ip->pm, 0, 0, width, height,
2015 AllPlanes, ZPixmap);
2016 ip->gc = createGC(theDisplay, ip->pm);
2017 ip->depth = depth;
2018 #if XSHM_SUPPORT
2019 ip->shminfo.shmid = -1;
2020 #endif
2021
2022 return ip;
2023 }
2024
2025 #if XSHM_SUPPORT
2026 static int shm_error;
my_err_handler(Display * dpy,XErrorEvent * e)2027 static int my_err_handler(Display* dpy, XErrorEvent* e)
2028 {
2029 shm_error = e->error_code;
2030 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
2031 "Warning: X Sherry Warning: Can't create SHM Pixmap. error-code=%d",
2032 shm_error);
2033 return shm_error;
2034 }
create_shm_image_pixmap(int width,int height,int depth)2035 static ImagePixmap *create_shm_image_pixmap(int width, int height, int depth)
2036 {
2037 XErrorHandler origh;
2038 ImagePixmap *ip;
2039 int shm_depth;
2040
2041 shm_depth = depth;
2042 ip = (ImagePixmap *)safe_malloc(sizeof(ImagePixmap));
2043
2044 shm_error = 0;
2045 origh = XSetErrorHandler(my_err_handler);
2046
2047 /* There is no need to initialize XShmSegmentInfo structure
2048 * before the call to XShmCreateImage.
2049 */
2050 ip->im = XShmCreateImage(theDisplay, theVisual, shm_depth,
2051 ZPixmap, NULL,
2052 &ip->shminfo, width, height);
2053 if(ip->im == NULL)
2054 {
2055 if(shm_error == 0)
2056 shm_error = -1;
2057 goto done;
2058 }
2059
2060 /* The next step is to create the shared memory segment.
2061 * The return value of shmat() should be stored both
2062 * the XImage structure and the shminfo structure.
2063 */
2064 ip->shminfo.shmid = shmget(IPC_PRIVATE,
2065 ip->im->bytes_per_line * ip->im->height,
2066 IPC_CREAT | 0777);
2067 if(ip->shminfo.shmid == -1)
2068 {
2069 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
2070 "X Sherry Warning: Can't create SHM Pixmap.\n"
2071 "shmget: %s", strerror(errno));
2072 XDestroyImage(ip->im);
2073 ip->im = NULL;
2074 shm_error = -1;
2075 goto done;
2076 }
2077 ip->shminfo.shmaddr = ip->im->data =
2078 (char *)shmat(ip->shminfo.shmid, NULL, 0);
2079 if(ip->shminfo.shmaddr == (void *)-1)
2080 {
2081 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
2082 "X Sherry Warning: Can't create SHM Pixmap.\n"
2083 "shmget: %s", strerror(errno));
2084 shmctl(ip->shminfo.shmid, IPC_RMID, NULL);
2085 XDestroyImage(ip->im);
2086 ip->im = NULL;
2087 shm_error = -1;
2088 goto done;
2089 }
2090
2091
2092 /* If readOnly is True, XShmGetImage calls will fail. */
2093 ip->shminfo.readOnly = False;
2094
2095
2096 /* Tell the server to attach to your shared memory segment. */
2097 if(XShmAttach(theDisplay, &ip->shminfo) == 0)
2098 {
2099 if(shm_error == 0)
2100 {
2101 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
2102 "X Sherry Warning: Can't create SHM Pixmap.\n"
2103 "Can't attach to the shared memory segment.");
2104 shm_error = -1;
2105 }
2106 shmdt(ip->shminfo.shmaddr);
2107 shmctl(ip->shminfo.shmid, IPC_RMID, NULL);
2108 XDestroyImage(ip->im);
2109 ip->im = NULL;
2110 goto done;
2111 }
2112
2113 XSync(theDisplay, False); /* Wait until ready. */
2114
2115 ip->pm = XShmCreatePixmap(theDisplay, theWindow, ip->im->data,
2116 &ip->shminfo, width, height, shm_depth);
2117 if(ip->pm == None)
2118 {
2119 if(shm_error == 0)
2120 {
2121 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
2122 "X Sherry Warning: Can't create SHM Pixmap.\n"
2123 "XShmCreatePixmap() is failed");
2124 shm_error = -1;
2125 }
2126 shmdt(ip->shminfo.shmaddr);
2127 shmctl(ip->shminfo.shmid, IPC_RMID, NULL);
2128 XDestroyImage(ip->im);
2129 ip->im = NULL;
2130 goto done;
2131 }
2132
2133 done:
2134 XSetErrorHandler(origh);
2135
2136 if(ip->im != NULL)
2137 {
2138 ip->gc = createGC(theDisplay, ip->pm);
2139 ip->depth = shm_depth;
2140 }
2141 else
2142 {
2143 free(ip);
2144 ip = create_image_pixmap(width, height, depth);
2145 }
2146 return ip;
2147 }
2148 #endif
2149
clear_image_pixmap(ImagePixmap * ip,unsigned long pixel)2150 static void clear_image_pixmap(ImagePixmap *ip, unsigned long pixel)
2151 {
2152 int x, y, w, h;
2153
2154 w = ip->im->width;
2155 h = ip->im->height;
2156
2157 XSetForeground(theDisplay, ip->gc, pixel);
2158 XFillRectangle(theDisplay, ip->pm, ip->gc,
2159 0, 0, ip->im->width, ip->im->height);
2160 #if XSHM_SUPPORT
2161 if(ip->shminfo.shmid != -1)
2162 return;
2163 #endif /* XSHM_SUPPORT */
2164 for(y = 0; y < h; y++)
2165 for(x = 0; x < w; x++){
2166 XPutPixel(ip->im, x, y, pixel);
2167 }
2168 }
2169
free_image_pixmap(ImagePixmap * ip)2170 static void free_image_pixmap(ImagePixmap *ip)
2171 {
2172 XFreePixmap(theDisplay, ip->pm);
2173
2174 #if XSHM_SUPPORT
2175 if(ip->shminfo.shmid != -1)
2176 {
2177 /* To destory a shard memory XImage, you should call XShmDetach()
2178 * first.
2179 */
2180 XShmDetach(theDisplay, &ip->shminfo);
2181
2182 /* Unmap shared memory segment */
2183 shmdt(ip->shminfo.shmaddr);
2184
2185 /* Remove a shared memory ID from the system */
2186 shmctl(ip->shminfo.shmid, IPC_RMID, NULL);
2187 }
2188 #endif /* XSHM_SUPPORT */
2189 XDestroyImage(ip->im);
2190 free(ip);
2191 }
2192
2193
2194 #define IS_MULTI_BYTE(c) (((c)&0x80) && \
2195 ((0x1 <= ((c)&0x7F) && ((c)&0x7F) <= 0x1f) || \
2196 (0x60 <= ((c)&0x7F) && ((c)&0x7F) <= 0x7c)))
2197
2198 /* bitmap_drawimage() Draws string into image
2199 * It returns number of bytes drawn
2200 */
bitmap_drawimage(ImagePixmap * ip,char * sjis_str,int nbytes)2201 static int bitmap_drawimage(ImagePixmap *ip, char *sjis_str, int nbytes)
2202 {
2203 int write_len;
2204 int sjis_c1, sjis_c2;
2205 int x, width, height;
2206
2207 x = write_len = 0;
2208 while(*sjis_str && write_len < IMAGEBITMAPLEN)
2209 {
2210 sjis_c1 = *sjis_str & 0xff;
2211 sjis_str++;
2212
2213 if(IS_MULTI_BYTE(sjis_c1))
2214 {
2215 int e1, e2;
2216 XChar2b b;
2217
2218 if(write_len+1 == IMAGEBITMAPLEN)
2219 break;
2220 sjis_c2 = *sjis_str & 0xff;
2221 if(sjis_c2 == 0)
2222 break;
2223 sjis_str++;
2224
2225 /* SJIS to EUC */
2226 if(sjis_c2 >= 0x9f)
2227 {
2228 if(sjis_c1 >= 0xe0)
2229 e1 = sjis_c1 * 2 - 0xe0;
2230 else
2231 e1 = sjis_c1 * 2 - 0x60;
2232 e2 = sjis_c2 + 2;
2233 }
2234 else
2235 {
2236 if(sjis_c1 >= 0xe0)
2237 e1 = sjis_c1 * 2 - 0xe1;
2238 else
2239 e1 = sjis_c1 * 2 - 0x61;
2240 if(sjis_c2 >= 0x7f)
2241 e2 = sjis_c2 + 0x60;
2242 else
2243 e2 = sjis_c2 + 0x61;
2244 }
2245
2246 b.byte1 = e1 & 0x7f;
2247 b.byte2 = e2 & 0x7f;
2248 XSetFont(theDisplay, ip->gc, theFont16->fid);
2249 XDrawImageString16(theDisplay, ip->pm, ip->gc,
2250 x - lbearing16, ascent16, &b, 1);
2251 x += CHAR_WIDTH2;
2252 write_len += 2;
2253 }
2254 else
2255 {
2256 char c = sjis_c1;
2257 XSetFont(theDisplay, ip->gc, theFont8->fid);
2258 XDrawImageString(theDisplay, ip->pm, ip->gc,
2259 x - lbearing8, ascent8, &c, 1);
2260 x += CHAR_WIDTH1;
2261 write_len++;
2262 }
2263 }
2264
2265 if(write_len == 0)
2266 return 0; /* Terminate repeating call */
2267
2268 #if XSHM_SUPPORT
2269 if(ip->shminfo.shmid != -1)
2270 {
2271 XSync(theDisplay, 0); /* Wait until ready */
2272 return write_len;
2273 }
2274 #endif /* XSHM_SUPPORT */
2275
2276 /* XSHM is not supported.
2277 * Now, re-allocate XImage structure from the pixmap.
2278 */
2279 width = ip->im->width;
2280 height = ip->im->height;
2281 XDestroyImage(ip->im);
2282 ip->im = XGetImage(theDisplay, ip->pm, 0, 0, width, height,
2283 AllPlanes, ZPixmap);
2284
2285 return write_len;
2286 }
2287
2288
2289 /**** VirtualScreen intarfaces ****/
alloc_vscreen(int width,int height,int transParent)2290 static VirtualScreen *alloc_vscreen(int width, int height, int transParent)
2291 {
2292 VirtualScreen *scr;
2293 int size = width * height;
2294
2295 /* Shared the allocated memory for data and the structure */
2296 scr = (VirtualScreen *)safe_malloc(sizeof(VirtualScreen) + size);
2297 scr->width = width;
2298 scr->height = height;
2299 scr->transParent = transParent;
2300 memset(scr->data, transParent, size);
2301 return scr;
2302 }
2303
free_vscreen(VirtualScreen * scr)2304 static void free_vscreen(VirtualScreen *scr)
2305 {
2306 free(scr);
2307 }
2308
x_sry_event(void)2309 void x_sry_event(void)
2310 {
2311 if(QLength(theDisplay) == 0)
2312 XSync(theDisplay, False);
2313 while(QLength(theDisplay) > 0)
2314 {
2315 XEvent e;
2316 XNextEvent(theDisplay, &e);
2317 switch(e.type)
2318 {
2319 case Expose:
2320 update_real_screen(e.xexpose.x, e.xexpose.y,
2321 e.xexpose.width, e.xexpose.height);
2322 break;
2323 }
2324 if(QLength(theDisplay) == 0)
2325 XSync(theDisplay, False);
2326 }
2327 }
2328 #endif /* ENABLE_SHERRY */
2329