rnd-20000718-1-src
[rocksndiamonds.git] / src / msdos.c
index f1dcfa473686ba19765dfae70497bd6021a702b9..d9dd5e7921a0cda09b312e4f6b5c7de7856a4086 100644 (file)
 #ifdef MSDOS
 
 #include "main.h"
+#include "misc.h"
 #include "tools.h"
 #include "sound.h"
 #include "files.h"
 #include "joystick.h"
 #include "image.h"
+#include "pcx.h"
 
+/* allegro driver declarations */
 DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
 DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
 DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
 DECLARE_MIDI_DRIVER_LIST()
 DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
 
-static int key_buffer[OSD_MAX_KEY];
+/* allegro global variables */
+extern volatile int key_shifts;
+extern int num_joysticks;
+extern JOYSTICK_INFO joy[];
+extern int i_love_bill;
+
+/* internal variables of msdos.c */
+static boolean keyboard_auto_repeat = TRUE;
+static int key_press_state[MAX_SCANCODES];
 static XEvent event_buffer[MAX_EVENT_BUFFER];
 static int pending_events;
 static boolean joystick_event;
@@ -42,9 +53,11 @@ static int global_colormap_entries_used = 0;
 
 boolean wait_for_vsync;
 
+/*
 extern int playing_sounds;
 extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
 extern struct SoundControl emptySoundControl;
+*/
 
 static BITMAP *Read_PCX_to_AllegroBitmap(char *);
 
@@ -54,27 +67,29 @@ static void allegro_drivers()
 
   for (i=0; i<MAX_EVENT_BUFFER; i++)
     event_buffer[i].type = 0;
-  for(i=0; i<OSD_MAX_KEY; i++)
-    key_buffer[i] = KeyReleaseMask;
+
+  for (i=0; i<MAX_SCANCODES; i++)
+    key_press_state[i] = KeyReleaseMask;
+
   last_mouse_pos = mouse_pos;
   last_mouse_b = 0;
 
   pending_events = 0;
   clear_keybuf();
 
+  /* enable Windows friendly timer mode (already default under Windows) */
   i_love_bill = TRUE;
+
   install_keyboard();
   install_timer();
   if (install_mouse() > 0)
     mouse_installed = TRUE;
-  install_joystick(JOY_TYPE_2PADS);
 
-  load_joystick_data(JOYSTICK_FILENAME);
   last_joystick_state = 0;
   joystick_event = FALSE;
 
   reserve_voices(MAX_SOUNDS_PLAYING, 0);
-  if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "ROCKS.SND") == -1)
+  if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
     if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
       sound_status = SOUND_OFF;
 }
@@ -98,131 +113,124 @@ static void unhide_mouse(Display *display)
     show_mouse(video_bitmap);
 }
 
-static int get_joystick_state()
+static KeySym ScancodeToKeySym(byte scancode)
 {
-  int state = 0;
-
-  /*!!!*/
-  int joystick_nr = 0; /* CHANGE THIS! */
-  /*!!!*/
-
-  poll_joystick();
-
-  if (joy[joystick_nr].stick[0].axis[0].d1)
-    state |= JOY_LEFT;
-  if (joy[joystick_nr].stick[0].axis[0].d2)
-    state |= JOY_RIGHT;
-  if (joy[joystick_nr].stick[0].axis[1].d1)
-    state |= JOY_UP;
-  if (joy[joystick_nr].stick[0].axis[1].d2)
-    state |= JOY_DOWN;
-  if (joy[joystick_nr].button[0].b)
-    state |= JOY_BUTTON_1;
-
-  switch (state)
+  switch(scancode)
   {
-    case (JOY_DOWN | JOY_LEFT):
-      state = XK_KP_1;
-      break;
-    case (JOY_DOWN):
-      state = XK_KP_2;
-      break;
-    case (JOY_DOWN | JOY_RIGHT):
-      state = XK_KP_3;
-      break;
-    case (JOY_LEFT):
-      state = XK_KP_4;
-      break;
-    case (JOY_RIGHT):
-      state = XK_KP_6;
-      break;
-    case (JOY_UP | JOY_LEFT):
-      state = XK_KP_7;
-      break;
-    case (JOY_UP):
-      state = XK_KP_8;
-      break;
-    case (JOY_UP | JOY_RIGHT):
-      state = XK_KP_9;
-      break;
-
-    case (JOY_DOWN | JOY_BUTTON_1):
-      state = XK_X;
-      break;
-    case (JOY_LEFT | JOY_BUTTON_1):
-      state = XK_S;
-      break;
-    case (JOY_RIGHT | JOY_BUTTON_1):
-      state = XK_D;
-      break;
-    case (JOY_UP | JOY_BUTTON_1):
-      state = XK_E;
-      break;
-   default:
-     state = 0;
+    case KEY_ESC:              return XK_Escape;
+    case KEY_1:                        return XK_1;
+    case KEY_2:                        return XK_2;
+    case KEY_3:                        return XK_3;
+    case KEY_4:                        return XK_4;
+    case KEY_5:                        return XK_5;
+    case KEY_6:                        return XK_6;
+    case KEY_7:                        return XK_7;
+    case KEY_8:                        return XK_8;
+    case KEY_9:                        return XK_9;
+    case KEY_0:                        return XK_0;
+    case KEY_MINUS:            return XK_minus;
+    case KEY_EQUALS:           return XK_equal;
+    case KEY_BACKSPACE:                return XK_BackSpace;
+    case KEY_TAB:              return XK_Tab;
+    case KEY_Q:                        return XK_q;
+    case KEY_W:                        return XK_w;
+    case KEY_E:                        return XK_e;
+    case KEY_R:                        return XK_r;
+    case KEY_T:                        return XK_t;
+    case KEY_Y:                        return XK_y;
+    case KEY_U:                        return XK_u;
+    case KEY_I:                        return XK_i;
+    case KEY_O:                        return XK_o;
+    case KEY_P:                        return XK_p;
+    case KEY_OPENBRACE:                return XK_braceleft;
+    case KEY_CLOSEBRACE:       return XK_braceright;
+    case KEY_ENTER:            return XK_Return;
+    case KEY_LCONTROL:         return XK_Control_L;
+    case KEY_A:                        return XK_a;
+    case KEY_S:                        return XK_s;
+    case KEY_D:                        return XK_d;
+    case KEY_F:                        return XK_f;
+    case KEY_G:                        return XK_g;
+    case KEY_H:                        return XK_h;
+    case KEY_J:                        return XK_j;
+    case KEY_K:                        return XK_k;
+    case KEY_L:                        return XK_l;
+    case KEY_COLON:            return XK_colon;
+    case KEY_QUOTE:            return XK_apostrophe;
+    case KEY_TILDE:            return XK_asciitilde;
+    case KEY_LSHIFT:           return XK_Shift_L;
+    case KEY_BACKSLASH:                return XK_backslash;
+    case KEY_Z:                        return XK_z;
+    case KEY_X:                        return XK_x;
+    case KEY_C:                        return XK_c;
+    case KEY_V:                        return XK_v;
+    case KEY_B:                        return XK_b;
+    case KEY_N:                        return XK_n;
+    case KEY_M:                        return XK_m;
+    case KEY_COMMA:            return XK_comma;
+    case KEY_STOP:             return XK_period;
+    case KEY_SLASH:            return XK_slash;
+    case KEY_RSHIFT:           return XK_Shift_R;
+    case KEY_ASTERISK:         return XK_KP_Multiply;
+    case KEY_ALT:              return XK_Alt_L;
+    case KEY_SPACE:            return XK_space;
+    case KEY_CAPSLOCK:         return XK_Caps_Lock;
+    case KEY_F1:               return XK_F1;
+    case KEY_F2:               return XK_F2;
+    case KEY_F3:               return XK_F3;
+    case KEY_F4:               return XK_F4;
+    case KEY_F5:               return XK_F5;
+    case KEY_F6:               return XK_F6;
+    case KEY_F7:               return XK_F7;
+    case KEY_F8:               return XK_F8;
+    case KEY_F9:               return XK_F9;
+    case KEY_F10:              return XK_F10;
+    case KEY_NUMLOCK:          return XK_Num_Lock;
+    case KEY_SCRLOCK:          return XK_Scroll_Lock;
+    case KEY_HOME:             return XK_Home;
+    case KEY_UP:               return XK_Up;
+    case KEY_PGUP:             return XK_Page_Up;
+    case KEY_MINUS_PAD:                return XK_KP_Subtract;
+    case KEY_LEFT:             return XK_Left;
+    case KEY_5_PAD:            return XK_KP_5;
+    case KEY_RIGHT:            return XK_Right;
+    case KEY_PLUS_PAD:         return XK_KP_Add;
+    case KEY_END:              return XK_End;
+    case KEY_DOWN:             return XK_Down;
+    case KEY_PGDN:             return XK_Page_Down;
+    case KEY_INSERT:           return XK_Insert;
+    case KEY_DEL:              return XK_Delete;
+    case KEY_PRTSCR:           return XK_Print;
+    case KEY_F11:              return XK_F11;
+    case KEY_F12:              return XK_F12;
+    case KEY_LWIN:             return XK_Meta_L;
+    case KEY_RWIN:             return XK_Meta_R;
+    case KEY_MENU:             return XK_Menu;
+    case KEY_PAD:              return XK_VoidSymbol;
+    case KEY_RCONTROL:         return XK_Control_R;
+    case KEY_ALTGR:            return XK_Alt_R;
+    case KEY_SLASH2:           return XK_KP_Divide;
+    case KEY_PAUSE:            return XK_Pause;
+
+    case NEW_KEY_BACKSLASH:    return XK_backslash;
+    case NEW_KEY_1_PAD:                return XK_KP_1;
+    case NEW_KEY_2_PAD:                return XK_KP_2;
+    case NEW_KEY_3_PAD:                return XK_KP_3;
+    case NEW_KEY_4_PAD:                return XK_KP_4;
+    case NEW_KEY_5_PAD:                return XK_KP_5;
+    case NEW_KEY_6_PAD:                return XK_KP_6;
+    case NEW_KEY_7_PAD:                return XK_KP_7;
+    case NEW_KEY_8_PAD:                return XK_KP_8;
+    case NEW_KEY_9_PAD:                return XK_KP_9;
+    case NEW_KEY_0_PAD:                return XK_KP_0;
+    case NEW_KEY_STOP_PAD:     return XK_KP_Separator;
+    case NEW_KEY_EQUALS_PAD:   return XK_KP_Equal;
+    case NEW_KEY_SLASH_PAD:    return XK_KP_Divide;
+    case NEW_KEY_ASTERISK_PAD: return XK_KP_Multiply;
+    case NEW_KEY_ENTER_PAD:    return XK_KP_Enter;
+
+    default:                   return XK_VoidSymbol;
   }
-
-  return state;
-}
-
-unsigned char get_ascii(KeySym key)
-{
-  switch(key)
-  {
-    case OSD_KEY_Q: return 'Q';
-    case OSD_KEY_W: return 'W';
-    case OSD_KEY_E: return 'E';
-    case OSD_KEY_R: return 'R';
-    case OSD_KEY_T: return 'T';
-    case OSD_KEY_Y: return 'Y';
-    case OSD_KEY_U: return 'U';
-    case OSD_KEY_I: return 'I';
-    case OSD_KEY_O: return 'O';
-    case OSD_KEY_P: return 'P';
-    case OSD_KEY_A: return 'A';
-    case OSD_KEY_S: return 'S';
-    case OSD_KEY_D: return 'D';
-    case OSD_KEY_F: return 'F';
-    case OSD_KEY_G: return 'G';
-    case OSD_KEY_H: return 'H';
-    case OSD_KEY_J: return 'J';
-    case OSD_KEY_K: return 'K';
-    case OSD_KEY_L: return 'L';
-    case OSD_KEY_Z: return 'Z';
-    case OSD_KEY_X: return 'X';
-    case OSD_KEY_C: return 'C';
-    case OSD_KEY_V: return 'V';
-    case OSD_KEY_B: return 'B';
-    case OSD_KEY_N: return 'N';
-    case OSD_KEY_M: return 'M';
-    case OSD_KEY_1: return '1';
-    case OSD_KEY_2: return '2';
-    case OSD_KEY_3: return '3';
-    case OSD_KEY_4: return '4';
-    case OSD_KEY_5: return '5';
-    case OSD_KEY_6: return '6';
-    case OSD_KEY_7: return '7';
-    case OSD_KEY_8: return '8';
-    case OSD_KEY_9: return '9';
-    case OSD_KEY_0: return '0';
-    case OSD_KEY_SPACE: return ' ';
-  }
-
-  return 0;
-}
-
-static long osd_key_pressed(int keycode)
-{
-  if (keycode == OSD_KEY_RCONTROL)
-    keycode = KEY_RCONTROL;
-  if (keycode == OSD_KEY_ALTGR)
-    keycode = KEY_ALTGR;
-
-  if (key[keycode])
-    return KeyPressMask;
-  else
-    return KeyReleaseMask;
 }
 
 void XMapWindow(Display *display, Window window)
@@ -243,22 +251,70 @@ void XMapWindow(Display *display, Window window)
     unhide_mouse(display);
 }
 
+static unsigned long AllocColorCell(int r, int g, int b)
+{
+  byte pixel_mapping = 0;
+  int i;
+
+  r >>= 10;
+  g >>= 10;
+  b >>= 10;
+
+  /* try to use existing colors from the global colormap */
+  for (i=0; i<global_colormap_entries_used; i++)
+  {
+    if (r == global_colormap[i].r &&
+       g == global_colormap[i].g &&
+       b == global_colormap[i].b)              /* color found */
+    {
+      pixel_mapping = i;
+      break;
+    }
+  }
+
+  if (i == global_colormap_entries_used)       /* color not found */
+  {
+    if (global_colormap_entries_used < MAX_COLORS)
+      global_colormap_entries_used++;
+
+    global_colormap[i].r = r;
+    global_colormap[i].g = g;
+    global_colormap[i].b = b;
+
+    pixel_mapping = i;
+  }
+
+  return pixel_mapping;
+}
+
 Display *XOpenDisplay(char *display_name)
 {
   Screen *screen;
   Display *display;
   BITMAP *mouse_bitmap = NULL;
+  char *filename;
 
-  screen = malloc(sizeof(Screen));
-  display = malloc(sizeof(Display));
+  filename = getPath3(options.ro_base_directory, GRAPHICS_DIRECTORY,
+                     MOUSE_FILENAME);
 
-  if ((mouse_bitmap = Read_PCX_to_AllegroBitmap(MOUSE_PCX_FILENAME)) == NULL)
+  mouse_bitmap = Read_PCX_to_AllegroBitmap(filename);
+  free(filename);
+
+  if (mouse_bitmap == NULL)
     return NULL;
 
+  screen = malloc(sizeof(Screen));
+  display = malloc(sizeof(Display));
+
   screen[0].cmap = 0;
   screen[0].root = 0;
+#if 0
   screen[0].white_pixel = 0xFF;
   screen[0].black_pixel = 0x00;
+#else
+  screen[0].white_pixel = AllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
+  screen[0].black_pixel = AllocColorCell(0x0000, 0x0000, 0x0000);
+#endif
   screen[0].video_bitmap = NULL;
 
   display->default_screen = 0;
@@ -292,6 +348,12 @@ Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
   display->screens[display->default_screen].height = YRES;
 
   set_mouse_sprite(display->mouse_ptr);
+
+#if 0
+  set_mouse_sprite_focus(1, 1);
+#endif
+
+  set_mouse_speed(1, 1);
   set_mouse_range(display->screens[display->default_screen].x + 1,
                  display->screens[display->default_screen].y + 1,
                  display->screens[display->default_screen].x + WIN_XSIZE + 1,
@@ -370,7 +432,7 @@ void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
     mouse_off = hide_mouse(display, x, y, width, height);
   }
 
-  rectfill((BITMAP *)d, x, y, x + width, y + height,
+  rectfill((BITMAP *)d, x, y, x + width - 1, y + height - 1,
           ((XGCValues *)gc)->foreground);
 
   if (mouse_off)
@@ -445,22 +507,35 @@ static BITMAP *Image_to_AllegroBitmap(Image *image)
   byte *src_ptr = image->data;
   byte pixel_mapping[MAX_COLORS];
   unsigned int depth = 8;
+
+#if 0
   int i, j, x, y;
+#else
+  int i, x, y;
+#endif
 
   /* allocate new allegro bitmap structure */
   if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
+  {
+    errno_pcx = PCX_NoMemory;
     return NULL;
+  }
 
   clear(bitmap);
 
   /* try to use existing colors from the global colormap */
   for (i=0; i<MAX_COLORS; i++)
   {
+
+#if 0
     int r, g, b;
+#endif
 
     if (!image->rgb.color_used[i])
       continue;
 
+
+#if 0
     r = image->rgb.red[i] >> 10;
     g = image->rgb.green[i] >> 10;
     b = image->rgb.blue[i] >> 10;
@@ -487,6 +562,12 @@ static BITMAP *Image_to_AllegroBitmap(Image *image)
 
       pixel_mapping[i] = j;
     }
+#else
+    pixel_mapping[i] = AllocColorCell(image->rgb.red[i],
+                                     image->rgb.green[i],
+                                     image->rgb.blue[i]);
+#endif
+
   }
 
   /* copy bitmap data */
@@ -510,7 +591,7 @@ static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
   if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
     return NULL;
 
-  set_pallete(global_colormap);
+  set_palette(global_colormap);
 
   return bitmap;
 }
@@ -521,7 +602,7 @@ int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
   BITMAP *bitmap;
 
   if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
-    return PCX_FileInvalid;
+    return errno_pcx;
 
   *pixmap = (Pixmap)bitmap;
   *pixmap_mask = (Pixmap)bitmap;
@@ -585,10 +666,15 @@ void XCloseDisplay(Display *display)
 
   if (is_screen_bitmap(bitmap))
     destroy_bitmap(bitmap);
+
   if (display->screens)
     free(display->screens);
+
   if (display)
     free(display);
+
+  /* return to text mode (or DOS box on Windows screen) */
+  set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
 }
 
 void XNextEvent(Display *display, XEvent *event_return)
@@ -600,77 +686,142 @@ void XNextEvent(Display *display, XEvent *event_return)
   pending_events--;
 }
 
-int XPending(Display *display)
+static void NewKeyEvent(int key_press_state, KeySym keysym)
 {
-  int i, state;
-  static boolean joy_button_2 = FALSE;
+  XKeyEvent *xkey;
 
-  /*!!!*/
-  int joystick_nr = 0; /* CHANGE THIS! */
-  /*!!!*/
+  if (pending_events >= MAX_EVENT_BUFFER)
+    return;
 
-  XKeyEvent *xkey;
-  XButtonEvent *xbutton;
-  XMotionEvent *xmotion;
+  pending_events++;
+  xkey = (XKeyEvent *)&event_buffer[pending_events];
+  xkey->type = key_press_state;
+  xkey->state = (unsigned int)keysym;
+}
 
-  /* joystick event (simulating keyboard event) */
+#define HANDLE_RAW_KB_ALL_KEYS                 0
+#define HANDLE_RAW_KB_MODIFIER_KEYS_ONLY       1
 
-  state = get_joystick_state();
+static int modifier_scancode[] =
+{
+  KEY_LSHIFT,
+  KEY_RSHIFT,
+  KEY_LCONTROL,
+  KEY_RCONTROL,
+  KEY_ALT,
+  KEY_ALTGR,
+  KEY_LWIN,
+  KEY_RWIN,
+  KEY_CAPSLOCK,
+  KEY_NUMLOCK,
+  KEY_SCRLOCK,
+  -1
+};
+
+static void HandleKeyboardRaw(int mode)
+{
+  int i;
 
-  if (joy[joystick_nr].button[1].b && !joy_button_2)
-  {
-    pending_events++;
-    xkey = (XKeyEvent *)&event_buffer[pending_events];
-    xkey->type = KeyPress;
-    xkey->state = XK_B;
-    joy_button_2 = TRUE;
-  }
-  else if (!joy[joystick_nr].button[1].b && joy_button_2)
+  for (i=0; i<MAX_SCANCODES; i++)
   {
-    pending_events++;
-    xkey = (XKeyEvent *)&event_buffer[pending_events];
-    xkey->type = KeyRelease;
-    xkey->state = XK_B;
-    joy_button_2 = FALSE;
+    int scancode, new_state, event_type;
+    char key_pressed;
+
+    if (mode == HANDLE_RAW_KB_MODIFIER_KEYS_ONLY)
+    {
+      if ((scancode = modifier_scancode[i]) == -1)
+       return;
+    }
+    else
+      scancode = i;
+
+    key_pressed = key[scancode];
+    new_state = (key_pressed ? KeyPressMask : KeyReleaseMask);
+    event_type = (key_pressed ? KeyPress : KeyRelease);
+
+    if (key_press_state[i] == new_state)       /* state not changed */
+      continue;
+
+    key_press_state[i] = new_state;
+
+    NewKeyEvent(event_type, ScancodeToKeySym(scancode));
   }
+}
 
-  if (state && !joystick_event)
+static void HandleKeyboardEvent()
+{
+  if (keypressed())
   {
-    pending_events++;
-    xkey = (XKeyEvent *)&event_buffer[pending_events];
-    xkey->type = KeyPress;
-    xkey->state = state;
-    joystick_event = TRUE;
-    last_joystick_state = state;
+    int key_info = readkey();
+    int scancode = (key_info >> 8);
+    int ascii = (key_info & 0xff);
+    KeySym keysym = ScancodeToKeySym(scancode);
+
+    if (scancode == KEY_PAD)
+    {
+      /* keys on the numeric keypad return just scancode 'KEY_PAD'
+        for some reason, so we must handle them separately */
+
+      if (ascii >= '0' && ascii <= '9')
+       keysym = XK_KP_0 + (KeySym)(ascii - '0');
+      else if (ascii == '.')
+       keysym = XK_KP_Separator;
+    }
+    else if (ascii >= ' ' && ascii <= 'Z')
+      keysym = XK_space + (KeySym)(ascii - ' ');
+    else if (ascii == '^')
+      keysym = XK_asciicircum;
+    else if (ascii == '_')
+      keysym = XK_underscore;
+    else if (ascii == 'Ä')
+      keysym = XK_Adiaeresis;
+    else if (ascii == 'Ö')
+      keysym = XK_Odiaeresis;
+    else if (ascii == 'Ü')
+      keysym = XK_Udiaeresis;
+    else if (ascii == 'ä')
+      keysym = XK_adiaeresis;
+    else if (ascii == 'ö')
+      keysym = XK_odiaeresis;
+    else if (ascii == 'ü')
+      keysym = XK_udiaeresis;
+    else if (ascii == 'ß')
+      keysym = XK_ssharp;
+
+    NewKeyEvent(KeyPress, keysym);
   }
-  else if ((state != last_joystick_state) && joystick_event)
+  else if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG))
   {
-    pending_events++;
-    xkey = (XKeyEvent *)&event_buffer[pending_events];
-    xkey->type = KeyRelease;
-    xkey->state = last_joystick_state;
-    joystick_event = FALSE;
+    /* the allegro function keypressed() does not give us single pressed
+       modifier keys, so we must detect them with the internal global
+       allegro variable 'key_shifts' and then handle them separately */
+
+    HandleKeyboardRaw(HANDLE_RAW_KB_MODIFIER_KEYS_ONLY);
   }
+}
 
-  /* keyboard event */
+int XPending(Display *display)
+{
+  XButtonEvent *xbutton;
+  XMotionEvent *xmotion;
+  int i;
 
-  for(i=0; i<OSD_MAX_KEY+1 && pending_events<MAX_EVENT_BUFFER; i++)
-  {
-    state = osd_key_pressed(i);
+  /* When using 'HandleKeyboardRaw()', keyboard input is also stored in
+     the allegro keyboard input buffer and would be available a second
+     time by calling 'HandleKeyboardEvent()'. To avoid double keyboard
+     events, the allegro function 'clear_keybuf()' must be called each
+     time when switching from calling 'HandleKeyboardRaw()' to calling
+     'HandleKeyboardEvent()' to get keyboard input, which is actually
+     done by 'XAutoRepeatOn()' which sets keyboard_auto_repeat to TRUE. */
 
-    if (state != key_buffer[i])
-    {
-      key_buffer[i] = state;
-      pending_events++;
-      xkey = (XKeyEvent *)&event_buffer[pending_events];
-      xkey->type = (state & KeyPressMask ? KeyPress : KeyRelease);
-      xkey->state = i;
-    }
-  }
+  /* keyboard event */
+  if (keyboard_auto_repeat)
+    HandleKeyboardEvent();
+  else
+    HandleKeyboardRaw(HANDLE_RAW_KB_ALL_KEYS);
 
   /* mouse motion event */
-
-  if (mouse_pos != last_mouse_pos && mouse_b != last_mouse_b)
+  if (mouse_pos != last_mouse_pos)
   {
     last_mouse_pos = mouse_pos;
     pending_events++;
@@ -678,26 +829,23 @@ int XPending(Display *display)
     xmotion->type = MotionNotify;
     xmotion->x = mouse_x - display->screens[display->default_screen].x;
     xmotion->y = mouse_y - display->screens[display->default_screen].y;
-
-
-    /*
-    return;
-    */
-
   }
 
   /* mouse button event */
-
   if (mouse_b != last_mouse_b)
   {
-    for(i=1; i<4; i<<=1)
+    for (i=0; i<3; i++)                /* check all three mouse buttons */
     {
-      if ((last_mouse_b & i) != (mouse_b & i))
+      int bitmask = (1 << i);
+
+      if ((last_mouse_b & bitmask) != (mouse_b & bitmask))
       {
+       int mapping[3] = { 1, 3, 2 };
+
        pending_events++;
         xbutton = (XButtonEvent *)&event_buffer[pending_events];
-        xbutton->type = (mouse_b & i ? ButtonPress : ButtonRelease);
-        xbutton->button = i;
+        xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease);
+        xbutton->button = mapping[i];
        xbutton->x = mouse_x - display->screens[display->default_screen].x;
        xbutton->y = mouse_y - display->screens[display->default_screen].y;
       }
@@ -713,60 +861,74 @@ KeySym XLookupKeysym(XKeyEvent *key_event, int index)
   return key_event->state;
 }
 
-void sound_handler(struct SoundControl snd_ctrl)
+int XLookupString(XKeyEvent *key_event, char *buffer, int buffer_size,
+                 KeySym *key, XComposeStatus *compose)
 {
-  int i;
+  *key = key_event->state;
+  return 0;
+}
 
-  if (snd_ctrl.fade_sound)
-  {
-    if (!playing_sounds)
-      return;
+void XSetForeground(Display *display, GC gc, unsigned long pixel)
+{
+  XGCValues *gcv = (XGCValues *)gc;
 
-    for(i=0; i<MAX_SOUNDS_PLAYING; i++)
-      if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) &&
-         !playlist[i].fade_sound)
-      {
-       playlist[i].fade_sound = TRUE;
-       if (voice_check(playlist[i].voice))
-         voice_ramp_volume(playlist[i].voice, 1000, 0);
-       playlist[i].loop = PSND_NO_LOOP;
-      }
-  }
-  else if (snd_ctrl.stop_all_sounds)
-  {
-    if (!playing_sounds)
-      return;
-    SoundServer_StopAllSounds();
-  }
-  else if (snd_ctrl.stop_sound)
+  gcv->foreground = pixel;
+}
+
+void XDrawLine(Display *display, Drawable d, GC gc,
+              int x1, int y1, int x2, int y2)
+{
+  XGCValues *gcv = (XGCValues *)gc;
+  boolean mouse_off = FALSE;
+
+  if ((BITMAP *)d == video_bitmap)
   {
-    if (!playing_sounds)
-      return;
-    SoundServer_StopSound(snd_ctrl.nr);
+    x1 += display->screens[display->default_screen].x;
+    y1 += display->screens[display->default_screen].y;
+    x2 += display->screens[display->default_screen].x;
+    y2 += display->screens[display->default_screen].y;
+    freeze_mouse_flag = TRUE;
+    mouse_off = hide_mouse(display, MIN(x1, x2), MIN(y1, y2),
+                          MAX(x1, x2) - MIN(x1, x2),
+                          MAX(y1, y2) - MIN(y1, y2));
   }
 
-  for(i=0; i<MAX_SOUNDS_PLAYING; i++)
-  {
-    if (!playlist[i].active || playlist[i].loop)
-      continue;
+  line((BITMAP *)d, x1, y1, x2, y2, gcv->foreground);
 
-    playlist[i].playingpos = voice_get_position(playlist[i].voice);
-    playlist[i].volume = voice_get_volume(playlist[i].voice);
-    if (playlist[i].playingpos == -1 || !playlist[i].volume)
-    {
-      deallocate_voice(playlist[i].voice);
-      playlist[i] = emptySoundControl;
-      playing_sounds--;
-    }
-  }
+  if (mouse_off)
+    unhide_mouse(display);
+
+  freeze_mouse_flag = FALSE;
+}
+
+void XDestroyImage(XImage *ximage)
+{
+}
+
+Bool XQueryPointer(Display *display, Window window,
+                  Window *root, Window *child, int *root_x, int *root_y,
+                  int *win_x, int *win_y, unsigned int *mask)
+{
+  *win_x = mouse_x - display->screens[display->default_screen].x;
+  *win_y = mouse_y - display->screens[display->default_screen].y;
+
+  return True;
+}
 
-  if (snd_ctrl.active)
-    SoundServer_InsertNewSound(snd_ctrl);
+void XAutoRepeatOn(Display *display)
+{
+  keyboard_auto_repeat = TRUE;
+  clear_keybuf();
+}
+
+void XAutoRepeatOff(Display *display)
+{
+  keyboard_auto_repeat = FALSE;
 }
 
 void NetworkServer(int port, int serveronly)
 {
-  printf("Sorry, networking not supported in DOS version.\n");
+  Error(ERR_WARN, "networking not supported in DOS version");
 }
 
 #endif /* MSDOS */