rnd-19981205-2
[rocksndiamonds.git] / src / msdos.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  msdos.c                                                 *
13 ***********************************************************/
14
15 #ifdef MSDOS
16
17 #include "main.h"
18 #include "misc.h"
19 #include "tools.h"
20 #include "sound.h"
21 #include "files.h"
22 #include "joystick.h"
23 #include "image.h"
24 #include "pcx.h"
25
26 /* allegro driver declarations */
27 DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
28 DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
29 DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
30 DECLARE_MIDI_DRIVER_LIST()
31 DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
32
33 /* allegro global variables */
34 extern volatile int key_shifts;
35 extern int num_joysticks;
36 extern JOYSTICK_INFO joy[];
37 extern int i_love_bill;
38
39 /* internal variables of msdos.c */
40 static int key_press_state[MAX_SCANCODES];
41 static XEvent event_buffer[MAX_EVENT_BUFFER];
42 static int pending_events;
43 static boolean joystick_event;
44 static boolean mouse_installed = FALSE;
45 static int last_mouse_pos;
46 static int last_mouse_b;
47 static int last_joystick_state;
48 static BITMAP* video_bitmap;
49
50 static RGB global_colormap[MAX_COLORS];
51 static int global_colormap_entries_used = 0;
52
53 boolean wait_for_vsync;
54
55 /*
56 extern int playing_sounds;
57 extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
58 extern struct SoundControl emptySoundControl;
59 */
60
61 static BITMAP *Read_PCX_to_AllegroBitmap(char *);
62
63 static void allegro_drivers()
64 {
65   int i;
66
67   for (i=0; i<MAX_EVENT_BUFFER; i++)
68     event_buffer[i].type = 0;
69
70   for (i=0; i<MAX_SCANCODES; i++)
71     key_press_state[i] = KeyReleaseMask;
72
73   last_mouse_pos = mouse_pos;
74   last_mouse_b = 0;
75
76   pending_events = 0;
77   clear_keybuf();
78
79   /* enable Windows friendly timer mode (already default under Windows) */
80   i_love_bill = TRUE;
81
82   install_keyboard();
83   install_timer();
84   if (install_mouse() > 0)
85     mouse_installed = TRUE;
86
87   last_joystick_state = 0;
88   joystick_event = FALSE;
89
90   reserve_voices(MAX_SOUNDS_PLAYING, 0);
91   if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
92     if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
93       sound_status = SOUND_OFF;
94 }
95
96 static boolean hide_mouse(Display *display, int x, int y,
97                           unsigned int width, unsigned int height)
98 {
99   if (mouse_x + display->mouse_ptr->w < x || mouse_x > x + width)
100     return FALSE;
101   if (mouse_y + display->mouse_ptr->h < y || mouse_y > y + height)
102     return FALSE;
103
104   show_mouse(NULL);
105
106   return TRUE;
107 }
108
109 static void unhide_mouse(Display *display)
110 {
111   if (mouse_installed)
112     show_mouse(video_bitmap);
113 }
114
115 static KeySym ScancodeToKeySym(byte scancode)
116 {
117   switch(scancode)
118   {
119     case KEY_ESC:               return XK_Escape;
120     case KEY_1:                 return XK_1;
121     case KEY_2:                 return XK_2;
122     case KEY_3:                 return XK_3;
123     case KEY_4:                 return XK_4;
124     case KEY_5:                 return XK_5;
125     case KEY_6:                 return XK_6;
126     case KEY_7:                 return XK_7;
127     case KEY_8:                 return XK_8;
128     case KEY_9:                 return XK_9;
129     case KEY_0:                 return XK_0;
130     case KEY_MINUS:             return XK_minus;
131     case KEY_EQUALS:            return XK_equal;
132     case KEY_BACKSPACE:         return XK_BackSpace;
133     case KEY_TAB:               return XK_Tab;
134     case KEY_Q:                 return XK_q;
135     case KEY_W:                 return XK_w;
136     case KEY_E:                 return XK_e;
137     case KEY_R:                 return XK_r;
138     case KEY_T:                 return XK_t;
139     case KEY_Y:                 return XK_y;
140     case KEY_U:                 return XK_u;
141     case KEY_I:                 return XK_i;
142     case KEY_O:                 return XK_o;
143     case KEY_P:                 return XK_p;
144     case KEY_OPENBRACE:         return XK_braceleft;
145     case KEY_CLOSEBRACE:        return XK_braceright;
146     case KEY_ENTER:             return XK_Return;
147     case KEY_LCONTROL:          return XK_Control_L;
148     case KEY_A:                 return XK_a;
149     case KEY_S:                 return XK_s;
150     case KEY_D:                 return XK_d;
151     case KEY_F:                 return XK_f;
152     case KEY_G:                 return XK_g;
153     case KEY_H:                 return XK_h;
154     case KEY_J:                 return XK_j;
155     case KEY_K:                 return XK_k;
156     case KEY_L:                 return XK_l;
157     case KEY_COLON:             return XK_colon;
158     case KEY_QUOTE:             return XK_apostrophe;
159     case KEY_TILDE:             return XK_asciitilde;
160     case KEY_LSHIFT:            return XK_Shift_L;
161     case KEY_BACKSLASH:         return XK_backslash;
162     case KEY_Z:                 return XK_z;
163     case KEY_X:                 return XK_x;
164     case KEY_C:                 return XK_c;
165     case KEY_V:                 return XK_v;
166     case KEY_B:                 return XK_b;
167     case KEY_N:                 return XK_n;
168     case KEY_M:                 return XK_m;
169     case KEY_COMMA:             return XK_comma;
170     case KEY_STOP:              return XK_period;
171     case KEY_SLASH:             return XK_slash;
172     case KEY_RSHIFT:            return XK_Shift_R;
173     case KEY_ASTERISK:          return XK_KP_Multiply;
174     case KEY_ALT:               return XK_Alt_L;
175     case KEY_SPACE:             return XK_space;
176     case KEY_CAPSLOCK:          return XK_Caps_Lock;
177     case KEY_F1:                return XK_F1;
178     case KEY_F2:                return XK_F2;
179     case KEY_F3:                return XK_F3;
180     case KEY_F4:                return XK_F4;
181     case KEY_F5:                return XK_F5;
182     case KEY_F6:                return XK_F6;
183     case KEY_F7:                return XK_F7;
184     case KEY_F8:                return XK_F8;
185     case KEY_F9:                return XK_F9;
186     case KEY_F10:               return XK_F10;
187     case KEY_NUMLOCK:           return XK_Num_Lock;
188     case KEY_SCRLOCK:           return XK_Scroll_Lock;
189     case KEY_HOME:              return XK_Home;
190     case KEY_UP:                return XK_Up;
191     case KEY_PGUP:              return XK_Page_Up;
192     case KEY_MINUS_PAD:         return XK_KP_Subtract;
193     case KEY_LEFT:              return XK_Left;
194     case KEY_5_PAD:             return XK_KP_5;
195     case KEY_RIGHT:             return XK_Right;
196     case KEY_PLUS_PAD:          return XK_KP_Add;
197     case KEY_END:               return XK_End;
198     case KEY_DOWN:              return XK_Down;
199     case KEY_PGDN:              return XK_Page_Down;
200     case KEY_INSERT:            return XK_Insert;
201     case KEY_DEL:               return XK_Delete;
202     case KEY_PRTSCR:            return XK_Print;
203     case KEY_F11:               return XK_F11;
204     case KEY_F12:               return XK_F12;
205     case KEY_LWIN:              return XK_Meta_L;
206     case KEY_RWIN:              return XK_Meta_R;
207     case KEY_MENU:              return XK_Menu;
208     case KEY_PAD:               return XK_VoidSymbol;
209     case KEY_RCONTROL:          return XK_Control_R;
210     case KEY_ALTGR:             return XK_Alt_R;
211     case KEY_SLASH2:            return XK_KP_Divide;
212     case KEY_PAUSE:             return XK_Pause;
213
214     case NEW_KEY_BACKSLASH:     return XK_backslash;
215     case NEW_KEY_1_PAD:         return XK_KP_1;
216     case NEW_KEY_2_PAD:         return XK_KP_2;
217     case NEW_KEY_3_PAD:         return XK_KP_3;
218     case NEW_KEY_4_PAD:         return XK_KP_4;
219     case NEW_KEY_5_PAD:         return XK_KP_5;
220     case NEW_KEY_6_PAD:         return XK_KP_6;
221     case NEW_KEY_7_PAD:         return XK_KP_7;
222     case NEW_KEY_8_PAD:         return XK_KP_8;
223     case NEW_KEY_9_PAD:         return XK_KP_9;
224     case NEW_KEY_0_PAD:         return XK_KP_0;
225     case NEW_KEY_STOP_PAD:      return XK_KP_Separator;
226     case NEW_KEY_EQUALS_PAD:    return XK_KP_Equal;
227     case NEW_KEY_SLASH_PAD:     return XK_KP_Divide;
228     case NEW_KEY_ASTERISK_PAD:  return XK_KP_Multiply;
229     case NEW_KEY_ENTER_PAD:     return XK_KP_Enter;
230
231     default:                    return XK_VoidSymbol;
232   }
233 }
234
235 void XMapWindow(Display *display, Window window)
236 {
237   int x, y;
238   unsigned int width, height;
239   boolean mouse_off;
240
241   x = display->screens[display->default_screen].x;
242   y = display->screens[display->default_screen].y;
243   width = display->screens[display->default_screen].width;
244   height = display->screens[display->default_screen].height;
245
246   mouse_off = hide_mouse(display, x, y, width, height);
247   blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
248
249   if (mouse_off)
250     unhide_mouse(display);
251 }
252
253 Display *XOpenDisplay(char *display_name)
254 {
255   Screen *screen;
256   Display *display;
257   BITMAP *mouse_bitmap = NULL;
258   char *filename;
259
260   filename = getPath3(options.base_directory, GRAPHICS_DIRECTORY,
261                       MOUSE_FILENAME);
262
263   mouse_bitmap = Read_PCX_to_AllegroBitmap(filename);
264   free(filename);
265
266   if (mouse_bitmap == NULL)
267     return NULL;
268
269   screen = malloc(sizeof(Screen));
270   display = malloc(sizeof(Display));
271
272   screen[0].cmap = 0;
273   screen[0].root = 0;
274   screen[0].white_pixel = 0xFF;
275   screen[0].black_pixel = 0x00;
276   screen[0].video_bitmap = NULL;
277
278   display->default_screen = 0;
279   display->screens = screen;
280   display->mouse_ptr = mouse_bitmap;
281
282   allegro_init();
283   allegro_drivers();
284   set_color_depth(8);
285
286   /* force Windows 95 to switch to fullscreen mode */
287   set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);
288   rest(200);
289   set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
290
291   return display;
292 }
293
294 Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
295                            unsigned int width, unsigned int height,
296                            unsigned int border_width, unsigned long border,
297                            unsigned long background)
298 {
299   video_bitmap = create_video_bitmap(XRES, YRES);
300   clear_to_color(video_bitmap, background);
301
302   display->screens[display->default_screen].video_bitmap = video_bitmap;
303   display->screens[display->default_screen].x = x;
304   display->screens[display->default_screen].y = y;
305   display->screens[display->default_screen].width = XRES;
306   display->screens[display->default_screen].height = YRES;
307
308   set_mouse_sprite(display->mouse_ptr);
309   set_mouse_speed(1, 1);
310   set_mouse_range(display->screens[display->default_screen].x + 1,
311                   display->screens[display->default_screen].y + 1,
312                   display->screens[display->default_screen].x + WIN_XSIZE + 1,
313                   display->screens[display->default_screen].y + WIN_YSIZE + 1);
314
315   show_video_bitmap(video_bitmap);
316
317   return (Window)video_bitmap;
318 }
319
320 Status XStringListToTextProperty(char **list, int count,
321                                  XTextProperty *text_prop_return)
322 {
323   char *string;
324
325   if (count >= 1)
326   {
327     string = malloc(strlen(list[0] + 1));
328     strcpy(string, list[0]);
329     text_prop_return->value = (unsigned char *)string;
330     return 1;
331   }
332   else
333     text_prop_return = NULL;
334
335   return 0;
336 }
337
338 void XFree(void *data)
339 {
340   if (data)
341     free(data);
342 }
343
344 GC XCreateGC(Display *display, Drawable d, unsigned long value_mask,
345              XGCValues *values)
346 {
347   XGCValues *gcv;
348   gcv = malloc(sizeof(XGCValues));
349   gcv->foreground = values->foreground;
350   gcv->background = values->background;
351   gcv->graphics_exposures = values->graphics_exposures;
352   gcv->clip_mask = values->clip_mask;
353   gcv->clip_x_origin = values->clip_x_origin;
354   gcv->clip_y_origin = values->clip_y_origin;
355   gcv->value_mask = value_mask;
356   return (GC)gcv;
357 }
358
359 void XSetClipMask(Display *display, GC gc, Pixmap pixmap)
360 {
361   XGCValues *gcv = (XGCValues *)gc;
362
363   gcv->clip_mask = pixmap;
364   gcv->value_mask |= GCClipMask;
365 }
366
367 void XSetClipOrigin(Display *display, GC gc, int x, int y)
368 {
369   XGCValues *gcv = (XGCValues *)gc;
370
371   gcv->clip_x_origin = x;
372   gcv->clip_x_origin = y;
373 }
374
375 void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
376                     unsigned int width, unsigned int height)
377 {
378   boolean mouse_off = FALSE;
379
380   if ((BITMAP *)d == video_bitmap)
381   {
382     x += display->screens[display->default_screen].x;
383     y += display->screens[display->default_screen].y;
384     freeze_mouse_flag = TRUE;
385     mouse_off = hide_mouse(display, x, y, width, height);
386   }
387
388   rectfill((BITMAP *)d, x, y, x + width, y + height,
389            ((XGCValues *)gc)->foreground);
390
391   if (mouse_off)
392     unhide_mouse(display);
393
394   freeze_mouse_flag = FALSE;
395 }
396
397 Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
398                      unsigned int height, unsigned int depth)
399 {
400   BITMAP *bitmap = NULL;
401
402   if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
403       width == FXSIZE && height == FYSIZE)
404     bitmap = create_video_bitmap(width, height);
405
406   if (bitmap == NULL)
407     bitmap = create_bitmap(width, height);
408
409   return (Pixmap)bitmap;
410 }
411
412 void XSync(Display *display, Bool discard_events)
413 {
414   wait_for_vsync = TRUE;
415 }
416
417 inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
418                       int src_x, int src_y,
419                       unsigned int width, unsigned int height,
420                       int dest_x, int dest_y)
421 {
422   boolean mouse_off = FALSE;
423
424   if ((BITMAP *)src == video_bitmap)
425   {
426     src_x += display->screens[display->default_screen].x;
427     src_y += display->screens[display->default_screen].y;
428   }
429
430   if ((BITMAP *)dest == video_bitmap)
431   {
432     dest_x += display->screens[display->default_screen].x;
433     dest_y += display->screens[display->default_screen].y;
434     freeze_mouse_flag = TRUE;
435     mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
436   }
437
438   if (wait_for_vsync)
439   {
440     wait_for_vsync = FALSE;
441     vsync();
442   }
443
444   if (((XGCValues *)gc)->value_mask & GCClipMask)
445     masked_blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
446                 width, height);
447   else
448     blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
449          width, height);
450
451   if (mouse_off)
452     unhide_mouse(display);
453
454   freeze_mouse_flag = FALSE;
455 }
456
457 static BITMAP *Image_to_AllegroBitmap(Image *image)
458 {
459   BITMAP *bitmap;
460   byte *src_ptr = image->data;
461   byte pixel_mapping[MAX_COLORS];
462   unsigned int depth = 8;
463   int i, j, x, y;
464
465   /* allocate new allegro bitmap structure */
466   if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
467     return NULL;
468
469   clear(bitmap);
470
471   /* try to use existing colors from the global colormap */
472   for (i=0; i<MAX_COLORS; i++)
473   {
474     int r, g, b;
475
476     if (!image->rgb.color_used[i])
477       continue;
478
479     r = image->rgb.red[i] >> 10;
480     g = image->rgb.green[i] >> 10;
481     b = image->rgb.blue[i] >> 10;
482
483     for (j=0; j<global_colormap_entries_used; j++)
484     {
485       if (r == global_colormap[j].r &&
486           g == global_colormap[j].g &&
487           b == global_colormap[j].b)            /* color found */
488       {
489         pixel_mapping[i] = j;
490         break;
491       }
492     }
493
494     if (j == global_colormap_entries_used)      /* color not found */
495     {
496       if (global_colormap_entries_used < MAX_COLORS)
497         global_colormap_entries_used++;
498
499       global_colormap[j].r = r;
500       global_colormap[j].g = g;
501       global_colormap[j].b = b;
502
503       pixel_mapping[i] = j;
504     }
505   }
506
507   /* copy bitmap data */
508   for (y=0; y<image->height; y++)
509     for (x=0; x<image->width; x++)
510       putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
511
512   return bitmap;
513 }
514
515 static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
516 {
517   BITMAP *bitmap;
518   Image *image;
519
520   /* read the graphic file in PCX format to internal image structure */
521   if ((image = Read_PCX_to_Image(filename)) == NULL)
522     return NULL;
523
524   /* convert internal image structure to allegro bitmap structure */
525   if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
526     return NULL;
527
528   set_pallete(global_colormap);
529
530   return bitmap;
531 }
532
533 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
534                        Pixmap *pixmap, Pixmap *pixmap_mask)
535 {
536   BITMAP *bitmap;
537
538   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
539     return PCX_FileInvalid;
540
541   *pixmap = (Pixmap)bitmap;
542   *pixmap_mask = (Pixmap)bitmap;
543
544   return PCX_Success;
545 }
546
547 int XpmReadFileToPixmap(Display *display, Drawable d, char *filename,
548                         Pixmap *pixmap_return, Pixmap *shapemask_return,
549                         XpmAttributes *attributes)
550 {
551   BITMAP *bitmap;
552
553   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
554     return XpmOpenFailed;
555
556   *pixmap_return = (Pixmap)bitmap;
557
558   return XpmSuccess;
559 }
560
561 int XReadBitmapFile(Display *display, Drawable d, char *filename,
562                     unsigned int *width_return, unsigned int *height_return,
563                     Pixmap *bitmap_return,
564                     int *x_hot_return, int *y_hot_return)
565 {
566   BITMAP *bitmap;
567
568   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
569     return BitmapOpenFailed;
570
571   *width_return = bitmap->w;
572   *height_return = bitmap->h;
573   *x_hot_return = -1;
574   *y_hot_return = -1;
575   *bitmap_return = (Pixmap)bitmap;
576
577   return BitmapSuccess;
578 }
579
580 void XFreePixmap(Display *display, Pixmap pixmap)
581 {
582   if (pixmap != DUMMY_MASK &&
583       (is_memory_bitmap((BITMAP *)pixmap) ||
584        is_screen_bitmap((BITMAP *)pixmap)))
585     destroy_bitmap((BITMAP *)pixmap);
586 }
587
588 void XFreeGC(Display *display, GC gc)
589 {
590   XGCValues *gcv;
591
592   gcv = (XGCValues *)gc;
593   if (gcv)
594     free(gcv);
595 }
596
597 void XCloseDisplay(Display *display)
598 {
599   BITMAP *bitmap = video_bitmap;
600
601   if (is_screen_bitmap(bitmap))
602     destroy_bitmap(bitmap);
603
604   if (display->screens)
605     free(display->screens);
606
607   if (display)
608     free(display);
609
610   /* return to text mode (or DOS box on Windows screen) */
611   set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
612 }
613
614 void XNextEvent(Display *display, XEvent *event_return)
615 {
616   while (!pending_events)
617     XPending(display);
618
619   memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
620   pending_events--;
621 }
622
623 static void NewKeyEvent(int key_press_state, KeySym keysym)
624 {
625   XKeyEvent *xkey;
626
627   if (pending_events >= MAX_EVENT_BUFFER)
628     return;
629
630   pending_events++;
631   xkey = (XKeyEvent *)&event_buffer[pending_events];
632   xkey->type = key_press_state;
633   xkey->state = (unsigned int)keysym;
634 }
635
636 #define HANDLE_RAW_KB_ALL_KEYS          0
637 #define HANDLE_RAW_KB_MODIFIER_KEYS_ONLY        1
638
639 static int modifier_scancode[] =
640 {
641   KEY_LSHIFT,
642   KEY_RSHIFT,
643   KEY_LCONTROL,
644   KEY_RCONTROL,
645   KEY_ALT,
646   KEY_ALTGR,
647   KEY_LWIN,
648   KEY_RWIN,
649   KEY_CAPSLOCK,
650   KEY_NUMLOCK,
651   KEY_SCRLOCK,
652   -1
653 };
654
655 static void HandleKeyboardRaw(int mode)
656 {
657   int i;
658
659   for (i=0; i<MAX_SCANCODES; i++)
660   {
661     int scancode, new_state, event_type;
662     char key_pressed;
663
664     if (mode == HANDLE_RAW_KB_MODIFIER_KEYS_ONLY)
665     {
666       if ((scancode = modifier_scancode[i]) == -1)
667         return;
668     }
669     else
670       scancode = i;
671
672     key_pressed = key[scancode];
673     new_state = (key_pressed ? KeyPressMask : KeyReleaseMask);
674     event_type = (key_pressed ? KeyPress : KeyRelease);
675
676     if (key_press_state[i] == new_state)        /* state not changed */
677       continue;
678
679     key_press_state[i] = new_state;
680
681     NewKeyEvent(event_type, ScancodeToKeySym(scancode));
682   }
683 }
684
685 static void HandleKeyboardEvent()
686 {
687   if (keypressed())
688   {
689     int key_info = readkey();
690     int scancode = (key_info >> 8);
691     int ascii = (key_info & 0xff);
692     KeySym keysym = ScancodeToKeySym(scancode);
693
694     if (scancode == KEY_PAD)
695     {
696       /* keys on the numeric keypad return just scancode 'KEY_PAD'
697          for some reason, so we must handle them separately */
698
699       if (ascii >= '0' && ascii <= '9')
700         keysym = XK_KP_0 + (KeySym)(ascii - '0');
701       else if (ascii == '.')
702         keysym = XK_KP_Separator;
703     }
704
705     NewKeyEvent(KeyPress, keysym);
706   }
707   else if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG))
708   {
709     /* the allegro function keypressed() does not give us single pressed
710        modifier keys, so we must detect them with the internal global
711        allegro variable 'key_shifts' and then handle them separately */
712
713     HandleKeyboardRaw(HANDLE_RAW_KB_MODIFIER_KEYS_ONLY);
714   }
715 }
716
717 int XPending(Display *display)
718 {
719   XButtonEvent *xbutton;
720   XMotionEvent *xmotion;
721   int i;
722
723   /* keyboard event */
724   if (game_status == PLAYING)
725     HandleKeyboardRaw(HANDLE_RAW_KB_ALL_KEYS);
726   else
727     HandleKeyboardEvent();
728
729   /* mouse motion event */
730   /* generate mouse motion event only if any mouse buttons are pressed */
731   if (mouse_pos != last_mouse_pos && mouse_b)
732   {
733     last_mouse_pos = mouse_pos;
734     pending_events++;
735     xmotion = (XMotionEvent *)&event_buffer[pending_events];
736     xmotion->type = MotionNotify;
737     xmotion->x = mouse_x - display->screens[display->default_screen].x;
738     xmotion->y = mouse_y - display->screens[display->default_screen].y;
739   }
740
741   /* mouse button event */
742   if (mouse_b != last_mouse_b)
743   {
744     for (i=0; i<3; i++)         /* check all three mouse buttons */
745     {
746       int bitmask = (1 << i);
747
748       if ((last_mouse_b & bitmask) != (mouse_b & bitmask))
749       {
750         int mapping[3] = { 1, 3, 2 };
751
752         pending_events++;
753         xbutton = (XButtonEvent *)&event_buffer[pending_events];
754         xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease);
755         xbutton->button = mapping[i];
756         xbutton->x = mouse_x - display->screens[display->default_screen].x;
757         xbutton->y = mouse_y - display->screens[display->default_screen].y;
758       }
759     }
760     last_mouse_b = mouse_b;
761   }
762
763   return pending_events;
764 }
765
766 KeySym XLookupKeysym(XKeyEvent *key_event, int index)
767 {
768   return key_event->state;
769 }
770
771 void NetworkServer(int port, int serveronly)
772 {
773   Error(ERR_WARN, "networking not supported in DOS version");
774 }
775
776 #endif /* MSDOS */