rnd-20040822-1-src
[rocksndiamonds.git] / src / game_em / graphics.c
1 /* 2000-08-13T14:36:17Z
2  *
3  * graphics manipulation crap
4  */
5
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8
9 #include "global.h"
10 #include "display.h"
11 #include "level.h"
12
13 #include <stdio.h>
14
15
16 #if defined(TARGET_X11)
17
18 unsigned int frame; /* current frame */
19 unsigned int screen_x; /* current scroll position */
20 unsigned int screen_y;
21
22 /* tiles currently on screen */
23 static unsigned short screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
24
25 static unsigned int colours[8];
26 static unsigned int colour_anim;
27
28 static void xdebug(char *msg)
29 {
30 #if 0
31   XSync(display, False);
32   printf("EM DEBUG: %s\n", msg);
33 #endif
34 }
35
36 static void colour_shuffle(void)
37 {
38   unsigned int i, j, k;
39
40   for (i = 0; i < 8; i++)
41     colours[i] = i;
42
43   for (i = 0; i < 8; i++)
44   {
45     Random = Random * 129 + 1;
46     j = (Random >> 10) & 7;
47     k = colours[i];
48     colours[i] = colours[j];
49     colours[j] = k;
50   }
51 }
52
53
54 /* copy the entire screen to the window at the scroll position
55  *
56  * perhaps use mit-shm to speed this up
57  */
58
59 void blitscreen(void)
60 {
61   unsigned int x = screen_x % (MAX_BUF_XSIZE * TILEX);
62   unsigned int y = screen_y % (MAX_BUF_YSIZE * TILEY);
63
64   xdebug("blitscreen");
65
66   if (em_game_status == EM_GAME_STATUS_MENU)
67   {
68     ClearRectangle(screenBitmap, 0, SCR_MENUY * TILEY,
69                    SCR_FIELDX * TILEX, (17 - SCR_MENUY) * TILEY);
70     BlitBitmap(scoreBitmap, screenBitmap, 0, 0, SCR_MENUX * TILEX, SCOREY,
71                0, SCR_MENUY * TILEY);
72   }
73
74   if (x < 2 * TILEX && y < 2 * TILEY)
75   {
76     BlitBitmap(screenBitmap, window, x, y,
77                SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
78   }
79   else if (x < 2 * TILEX && y >= 2 * TILEY)
80   {
81     BlitBitmap(screenBitmap, window, x, y,
82                SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
83                SX, SY);
84     BlitBitmap(screenBitmap, window, x, 0,
85                SCR_FIELDX * TILEX, y - 2 * TILEY,
86                SX, SY + MAX_BUF_YSIZE * TILEY - y);
87   }
88   else if (x >= 2 * TILEX && y < 2 * TILEY)
89   {
90     BlitBitmap(screenBitmap, window, x, y,
91                MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
92                SX, SY);
93     BlitBitmap(screenBitmap, window, 0, y,
94                x - 2 * TILEX, SCR_FIELDY * TILEY,
95                SX + MAX_BUF_XSIZE * TILEX - x, SY);
96   }
97   else
98   {
99     BlitBitmap(screenBitmap, window, x, y,
100                MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
101                SX, SY);
102     BlitBitmap(screenBitmap, window, 0, y,
103                x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
104                SX + MAX_BUF_XSIZE * TILEX - x, SY);
105     BlitBitmap(screenBitmap, window, x, 0,
106                MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
107                SX, SY + MAX_BUF_YSIZE * TILEY - y);
108     BlitBitmap(screenBitmap, window, 0, 0,
109                x - 2 * TILEX, y - 2 * TILEY,
110                SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
111   }
112
113   /* draw either the main menu footer or the in-game time/gems/score values */
114
115   if (em_game_status == EM_GAME_STATUS_PLAY)
116     BlitBitmap(scoreBitmap, window, 0, 0, SCR_FIELDX * TILEX, SCOREY,
117                SX, SY + SCR_FIELDY * TILEY - SCOREY);
118
119   XFlush(display);
120
121   xdebug("blitscreen - done");
122 }
123
124
125 /* draw differences between game tiles and screen tiles
126  *
127  * implicitly handles scrolling and restoring background under the sprites
128  *
129  * perhaps use mit-shm to speed this up
130  */
131
132 static void animscreen(void)
133 {
134   unsigned int x, y, dx, dy;
135   unsigned short obj;
136   unsigned int left = screen_x / TILEX;
137   unsigned int top = screen_y / TILEY;
138
139   xdebug("animscreen");
140
141   for (y = top; y < top + MAX_BUF_YSIZE; y++)
142   {
143     dy = y % MAX_BUF_YSIZE;
144     for (x = left; x < left + MAX_BUF_XSIZE; x++)
145     {
146       dx = x % MAX_BUF_XSIZE;
147       obj = map_obj[frame][Draw[y][x]];
148
149       if (screentiles[dy][dx] != obj)
150       {
151         screentiles[dy][dx] = obj;
152         BlitBitmap(objBitmap, screenBitmap,
153                    (obj / 512) * TILEX, (obj % 512) * TILEY / 16,
154                    TILEX, TILEY, dx * TILEX, dy * TILEY);
155       }
156     }
157   }
158 }
159
160
161 /* blit players to the screen
162  *
163  * handles transparency and movement
164  */
165
166 static void blitplayer(struct PLAYER *ply)
167 {
168   unsigned int x, y, dx, dy;
169   unsigned short obj, spr;
170
171   xdebug("blitplayer");
172
173   if (ply->alive)
174   {
175     x = (frame * ply->oldx + (8 - frame) * ply->x) * TILEX / 8;
176     y = (frame * ply->oldy + (8 - frame) * ply->y) * TILEY / 8;
177     dx = x + TILEX - 1;
178     dy = y + TILEY - 1;
179
180     if ((unsigned int)(dx - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
181         (unsigned int)(dy - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
182     {
183       spr = map_spr[ply->num][frame][ply->anim];
184       x  %= MAX_BUF_XSIZE * TILEX;
185       y  %= MAX_BUF_YSIZE * TILEY;
186       dx %= MAX_BUF_XSIZE * TILEX;
187       dy %= MAX_BUF_YSIZE * TILEY;
188
189       if (objmaskBitmap)
190       {
191         obj = screentiles[y / TILEY][x / TILEX];
192         XCopyArea(display, objmaskBitmap, spriteBitmap, spriteGC,
193                   (obj / 512) * TILEX, (obj % 512) * TILEY / 16, TILEX, TILEY,
194                   -(x % TILEX), -(y % TILEY));
195
196         obj = screentiles[dy / TILEY][dx / TILEX];
197         XCopyArea(display, objmaskBitmap, spriteBitmap, spriteGC,
198                   (obj / 512) * TILEX, (obj % 512) * TILEY / 16, TILEX, TILEY,
199                   (MAX_BUF_XSIZE * TILEX - x) % TILEX,
200                   (MAX_BUF_YSIZE * TILEY - y) % TILEY);
201       }
202       else if (sprmaskBitmap)
203       {
204         XCopyArea(display, sprmaskBitmap, spriteBitmap, spriteGC,
205                   (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY, 0, 0);
206       }
207       else
208       {
209         XFillRectangle(display, spriteBitmap, spriteGC, 0, 0, TILEX, TILEY);
210       }
211
212       screentiles[y / TILEY][x / TILEX] = -1; /* mark screen as dirty */
213       screentiles[dy / TILEY][dx / TILEX] = -1;
214
215 #if 1
216
217
218 #if 1
219
220       SetClipMask(sprBitmap, sprBitmap->stored_clip_gc, spriteBitmap);
221
222       SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc, x, y);
223       BlitBitmapMasked(sprBitmap, screenBitmap,
224                        (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
225                        x, y);
226
227       SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc,
228                     x - MAX_BUF_XSIZE * TILEX, y);
229       BlitBitmapMasked(sprBitmap, screenBitmap,
230                        (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
231                        x - MAX_BUF_XSIZE * TILEX, y);
232
233       SetClipOrigin(sprBitmap, sprBitmap->stored_clip_gc,
234                     x, y - MAX_BUF_YSIZE * TILEY);
235       BlitBitmapMasked(sprBitmap, screenBitmap,
236                        (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
237                        x, y - MAX_BUF_YSIZE * TILEY);
238
239       SetClipMask(sprBitmap, sprBitmap->stored_clip_gc, None);
240
241 #else
242
243       XSetClipMask(display, sprBitmap->stored_clip_gc, spriteBitmap);
244
245       XSetClipOrigin(display, sprBitmap->stored_clip_gc, x, y);
246       XCopyArea(display, sprBitmap->drawable, screenBitmap->drawable,
247                 sprBitmap->stored_clip_gc,
248                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
249                 x, y);
250
251       XSetClipOrigin(display, sprBitmap->stored_clip_gc,
252                      x - MAX_BUF_XSIZE * TILEX, y);
253       XCopyArea(display, sprBitmap->drawable, screenBitmap->drawable,
254                 sprBitmap->stored_clip_gc,
255                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
256                 x - MAX_BUF_XSIZE * TILEX, y);
257
258       XSetClipOrigin(display, sprBitmap->stored_clip_gc,
259                      x, y - MAX_BUF_YSIZE * TILEY);
260       XCopyArea(display, sprBitmap->drawable, screenBitmap->drawable,
261                 sprBitmap->stored_clip_gc,
262                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
263                 x, y - MAX_BUF_YSIZE * TILEY);
264
265       XSetClipMask(display, sprBitmap->stored_clip_gc, None);
266
267 #endif
268
269 #else
270
271       XSetClipMask(display, screenGC, spriteBitmap);
272       XSetClipOrigin(display, screenGC, x, y);
273       XCopyArea(display, sprPixmap, screenPixmap, screenGC,
274                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
275                 x, y);
276       XSetClipOrigin(display, screenGC, x - MAX_BUF_XSIZE * TILEX, y);
277       XCopyArea(display, sprPixmap, screenPixmap, screenGC,
278                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
279                 x - MAX_BUF_XSIZE * TILEX, y);
280       XSetClipOrigin(display, screenGC, x, y - MAX_BUF_YSIZE * TILEY);
281       XCopyArea(display, sprPixmap, screenPixmap, screenGC,
282                 (spr / 8) * TILEX, (spr % 8) * TILEY, TILEX, TILEY,
283                 x, y - MAX_BUF_YSIZE * TILEY);
284       XSetClipMask(display, screenGC, None);
285
286 #endif
287     }
288   }
289 }
290
291
292 /* draw static text for time, gems and score counter */
293
294 void game_initscreen(void)
295 {
296   unsigned int x,y;
297
298   xdebug("game_initscreen");
299
300   frame = 6;
301   screen_x = 0;
302   screen_y = 0;
303
304   for (y = 0; y < MAX_BUF_YSIZE; y++)
305     for (x = 0; x < MAX_BUF_XSIZE; x++)
306       screentiles[y][x] = -1;
307
308   colour_shuffle();
309   colours[0] += 16;
310   colours[1] += 16;
311   colours[2] += 16;
312   colour_anim = 0;
313
314   ClearRectangle(scoreBitmap, 0, 0, SCR_FIELDX * TILEX, SCOREY);
315   BlitBitmap(botBitmap, scoreBitmap,
316              11 * SCOREX, colours[0] * SCOREY, 3 * SCOREX, SCOREY,
317              1 * SCOREX, 0);                            /* 0-63 time */
318   BlitBitmap(botBitmap, scoreBitmap,
319              18 * SCOREX, colours[0] * SCOREY, 6 * SCOREX, SCOREY,
320              11 * SCOREX, 0);                           /* 112-207 diamonds */
321   BlitBitmap(botBitmap, scoreBitmap,
322              14 * SCOREX, colours[0] * SCOREY, 4 * SCOREX, SCOREY,
323              24 * SCOREX, 0);                           /* 256-319 score */
324 }
325
326
327 /* draw current values for time, gems and score counter */
328
329 void game_blitscore(void)
330 {
331   unsigned int i;
332
333   xdebug("game_blitscore");
334
335   i = (lev.time + 4) / 5;
336   BlitBitmap(botBitmap, scoreBitmap,
337              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
338              7 * SCOREX, 0); i /= 10;
339   BlitBitmap(botBitmap, scoreBitmap,
340              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
341              6 * SCOREX, 0); i /= 10;
342   BlitBitmap(botBitmap, scoreBitmap,
343              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
344              5 * SCOREX, 0); i /= 10;
345   BlitBitmap(botBitmap, scoreBitmap,
346              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
347              4 * SCOREX, 0);
348
349   i = lev.score;
350   BlitBitmap(botBitmap, scoreBitmap,
351              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
352              31 * SCOREX, 0); i /= 10;
353   BlitBitmap(botBitmap, scoreBitmap,
354              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
355              30 * SCOREX, 0); i /= 10;
356   BlitBitmap(botBitmap, scoreBitmap,
357              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
358              29 * SCOREX, 0); i /= 10;
359   BlitBitmap(botBitmap, scoreBitmap,
360              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
361              28 * SCOREX, 0);
362
363   if (lev.home == 0)
364   {
365     BlitBitmap(botBitmap, scoreBitmap,
366                12 * SCOREX, 24 * SCOREY, 12 * SCOREX, SCOREY,
367                14 * SCOREX, 0); /* relax */
368
369     goto done;
370   }
371
372   if (ply1.alive + ply2.alive >= lev.home && lev.required == 0)
373   {
374     BlitBitmap(botBitmap, scoreBitmap,
375                24 * SCOREX, colours[2] * SCOREY, 12 * SCOREX, SCOREY,
376                14 * SCOREX, 0); /* find the exit */
377
378     goto done;
379   }
380
381   if (ply1.alive + ply2.alive < lev.home)
382   {
383     if (++colour_anim > 11)
384       colour_anim = 0;
385
386     if (colour_anim < 6)
387     {
388       BlitBitmap(botBitmap, scoreBitmap,
389                  0, 24 * SCOREY, 12 * SCOREX, SCOREY,
390                  14 * SCOREX, 0); /* forget it */
391
392       goto done;
393     }
394
395     BlitBitmap(botBitmap, scoreBitmap,
396                18 * SCOREX, colours[0] * SCOREY, 6 * SCOREX, SCOREY,
397                15 * SCOREX, 0); /* diamonds */
398   }
399
400   i = lev.required;
401   BlitBitmap(botBitmap, scoreBitmap,
402              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
403              20 * SCOREX, 0);
404   i /= 10;
405   BlitBitmap(botBitmap, scoreBitmap,
406              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
407              19 * SCOREX, 0);
408   i /= 10;
409   BlitBitmap(botBitmap, scoreBitmap,
410              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
411              18 * SCOREX, 0);
412   i /= 10;
413   BlitBitmap(botBitmap, scoreBitmap,
414              (i % 10) * SCOREX, colours[1] * SCOREY, SCOREX, SCOREY,
415              17 * SCOREX, 0);
416
417  done:
418 }
419
420 void game_animscreen(void)
421 {
422   unsigned int x,y;
423
424   xdebug("game_animscreen");
425
426   x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
427     + ((SCR_FIELDX - 1) * TILEX) / 2;
428   y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
429     + ((SCR_FIELDY - 1) * TILEY) / 2;
430
431   if (x > lev.width * TILEX)
432     x = lev.width * TILEX;
433   if (y > lev.height * TILEY)
434     y = lev.height * TILEY;
435
436   if (x < SCR_FIELDX * TILEX)
437     x = SCR_FIELDX * TILEY;
438   if (y < SCR_FIELDY * TILEY)
439     y = SCR_FIELDY * TILEY;
440
441   screen_x = x - (SCR_FIELDX - 1) * TILEX;
442   screen_y = y - (SCR_FIELDY - 1) * TILEY;
443
444   animscreen();
445   blitplayer(&ply1);
446   blitplayer(&ply2);
447   blitscreen();
448
449   XFlush(display);
450
451   Random = Random * 129 + 1;
452 }
453
454
455 /* draw main menu background and copyright note */
456
457 void title_initscreen(void)
458 {
459   xdebug("title_initscreen");
460
461   screen_x = 0;
462   screen_y = 0;
463
464   colour_shuffle();
465   colours[1] += 8;
466   colour_anim = 0;
467
468 #if 1
469
470   /* draw title screen on menu background */
471
472   BlitBitmap(ttlBitmap, screenBitmap, ORIG_MENU_SX, ORIG_MENU_SY,
473              SCR_MENUX * TILEX, SCR_MENUY * TILEY, 0, 0);
474
475   /* draw copyright note at footer */
476
477   if (botmaskBitmap)
478   {
479     BlitBitmap(botBitmap, scoreBitmap, 0, colours[1] * SCOREY,
480                SCR_MENUX * TILEX, SCOREY, 0, 0);
481
482     SetClipOrigin(botBitmap, botBitmap->stored_clip_gc,
483                   0, 0 - colours[0] * SCOREY);
484   }
485
486   BlitBitmapMasked(botBitmap, scoreBitmap, 0, colours[0] * SCOREY,
487                    SCR_MENUX * TILEX, SCOREY, 0, 0);
488
489 #else
490
491   XCopyArea(display, ttlPixmap, screenPixmap, screenGC,
492             0, 0, SCR_MENUX * TILEX, SCR_MENUY * TILEY, 0, 0);
493
494   if (botmaskBitmap)
495   {
496     XCopyArea(display, botPixmap, scorePixmap, scoreGC,
497               0, colours[1] * SCOREY, SCR_MENUX * TILEX, SCOREY, 0, 0);
498     XSetClipMask(display, scoreGC, botmaskBitmap);
499     XSetClipOrigin(display, scoreGC, 0, 0 - colours[0] * SCOREY);
500   }
501
502   XCopyArea(display, botPixmap, scorePixmap, scoreGC,
503             0, colours[0] * SCOREY, SCR_MENUX * TILEX, SCOREY, 0, 0);
504
505   if (botmaskBitmap)
506     XSetClipMask(display, scoreGC, None);
507
508 #endif
509 }
510
511
512 /* draw bouncing ball on main menu footer */
513
514 void title_blitscore(void)
515 {
516   unsigned int x, y, i;
517
518   xdebug("title_blitscore");
519
520   if (++colour_anim > 30)
521     colour_anim = 0;
522
523   i = colour_anim >= 16 ? 31 - colour_anim : colour_anim;
524   x = (i / 8 + 18) * 2 * SCOREX;
525   y = (i % 8 + 16) * SCOREY;
526
527 #if 1
528   if (botmaskBitmap)
529   {
530     BlitBitmap(botBitmap, scoreBitmap,
531                32 * SCOREX, colours[1] * SCOREY, 2 * SCOREX, SCOREY,
532                32 * SCOREX, 0);
533
534     SetClipOrigin(botBitmap, botBitmap->stored_clip_gc,
535                   32 * SCOREX - x, 0 - y);
536   }
537
538   BlitBitmapMasked(botBitmap, scoreBitmap,
539                    x, y, 2 * SCOREX, SCOREY, 32 * SCOREX, 0);
540
541 #else
542
543   if (botmaskBitmap)
544   {
545     XCopyArea(display, botPixmap, scorePixmap, scoreGC,
546               32 * SCOREX, colours[1] * SCOREY, 2 * SCOREX, SCOREY,
547               32 * SCOREX, 0);
548     XSetClipMask(display, scoreGC, botmaskBitmap);
549     XSetClipOrigin(display, scoreGC, 32 * SCOREX - x, 0 - y);
550   }
551
552   XCopyArea(display, botPixmap, scorePixmap, scoreGC,
553             x, y, 2 * SCOREX, SCOREY, 32 * SCOREX, 0);
554
555   if (botmaskBitmap)
556     XSetClipMask(display, scoreGC, None);
557 #endif
558 }
559
560 void title_blitants(unsigned int y)
561 {
562   static const char ants_dashes[2] = { 8, 7 };
563
564   xdebug("title_blitants");
565
566   XSetDashes(display, antsGC, colour_anim, ants_dashes, 2);
567   XDrawRectangle(display, screenPixmap, antsGC,
568                  0, y * TILEY, SCR_MENUX * TILEX - 1, TILEY - 1);
569 }
570
571 void title_animscreen(void)
572 {
573   blitscreen();
574   XFlush(display);
575
576   Random = Random * 129 + 1;
577 }
578
579 static int ttl_map[] =
580 {
581   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
582   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
583   -1,0,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,2,3,4,-1,      /* !',-. */
584   5,6,7,8,9,10,11,12,13,14,15,-1,-1,-1,-1,16,      /* 0123456789:? */
585   -1,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, /* ABCDEFGHIJKLMNO */
586   32,33,34,35,36,37,38,39,40,41,42,-1,-1,-1,-1,-1, /* PQRSTUVWXYZ */
587   -1,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, /* abcdefghijklmno */
588   32,33,34,35,36,37,38,39,40,41,42,-1,-1,-1,-1,-1  /* pqrstuvwxyz */
589 };
590
591 void title_string(unsigned int y, unsigned int left, unsigned int right,
592                   char *string)
593 {
594   int i;
595   unsigned int x;
596
597   xdebug("title_string");
598
599   y *= TILEY;
600   left *= SCOREX;
601   right *= SCOREX;
602
603   x = (left + right - strlen(string) * MENUFONTX) / 2;
604   if (x < left || x >= right)
605     x = left;
606
607   /* restore background graphic where text will be drawn */
608   BlitBitmap(ttlBitmap, screenBitmap, ORIG_MENU_SX + left, ORIG_MENU_SY + y,
609              right - left, MENUFONTY, left, y);
610
611 #if 1
612 #else
613   if (ttlmaskBitmap)
614     XSetClipMask(display, screenGC, ttlmaskBitmap);
615 #endif
616
617   for (i = 0; string[i] && x < right; i++)
618   {
619     int ch_pos, ch_x, ch_y;
620
621     ch_pos = ttl_map[string[i] & 127];
622
623     if (ch_pos == -1 || ch_pos > 22 * 2)
624       continue;                         /* no graphic for this character */
625
626     ch_x = (ch_pos % 22) * GFXMENUFONTX;
627     ch_y = (ch_pos / 22 + 12) * TILEY;
628
629 #if 1
630     SetClipOrigin(ttlBitmap, ttlBitmap->stored_clip_gc,
631                   x - ORIG_MENU_SX - ch_x, y - ORIG_MENU_SY - ch_y);
632
633     BlitBitmapMasked(ttlBitmap, screenBitmap, ch_x, ch_y, MENUFONTX, MENUFONTY,
634                      x - ORIG_MENU_SX, y - ORIG_MENU_SY);
635 #else
636     if (ttlmaskBitmap)
637       XSetClipOrigin(display, screenGC, x - ch_x, y - ch_y);
638
639     XCopyArea(display, ttlPixmap, screenPixmap, screenGC,
640               ch_x, ch_y, MENUFONTX, MENUFONTY, x, y);
641 #endif
642
643     x += MENUFONTX;
644   }
645
646 #if 1
647 #else
648   XSetClipMask(display, screenGC, None);
649 #endif
650 }
651
652 #endif