예제 #1
0
파일: savegame.cpp 프로젝트: CisBetter/ags
PStream StartSavegame(const String &filename, const String &user_text, const Bitmap *user_image)
{
    Stream *out = Common::File::CreateFile(filename);
    if (!out)
        return PStream();

    // Initialize and write Vista header
    RICH_GAME_MEDIA_HEADER vistaHeader;
    memset(&vistaHeader, 0, sizeof(RICH_GAME_MEDIA_HEADER));
    memcpy(&vistaHeader.dwMagicNumber, RM_MAGICNUMBER, sizeof(int));
    vistaHeader.dwHeaderVersion = 1;
    vistaHeader.dwHeaderSize = sizeof(RICH_GAME_MEDIA_HEADER);
    vistaHeader.dwThumbnailOffsetHigherDword = 0;
    vistaHeader.dwThumbnailOffsetLowerDword = 0;
    vistaHeader.dwThumbnailSize = 0;
    convert_guid_from_text_to_binary(game.guid, &vistaHeader.guidGameId[0]);
    uconvert(game.gamename, U_ASCII, (char*)&vistaHeader.szGameName[0], U_UNICODE, RM_MAXLENGTH);
    uconvert(user_text, U_ASCII, (char*)&vistaHeader.szSaveName[0], U_UNICODE, RM_MAXLENGTH);
    vistaHeader.szLevelName[0] = 0;
    vistaHeader.szComments[0] = 0;
    // MS Windows Vista rich media header
    vistaHeader.WriteToFile(out);

    // Savegame signature
    out->Write(SavegameSource::Signature.GetCStr(), SavegameSource::Signature.GetLength());

    // CHECKME: what is this plugin hook suppose to mean, and if it is called here correctly
    pl_run_plugin_hooks(AGSE_PRESAVEGAME, 0);

    // Write descrition block
    WriteDescription(out, user_text, user_image);
    return PStream(out);
}
예제 #2
0
/* sys_directx_message:
 *  Displays a message.
 */
static void sys_directx_message(AL_CONST char *msg)
{
    char *tmp1 = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE);
    char tmp2[WND_TITLE_SIZE*2];
    HWND allegro_wnd = win_get_window();

    while ((ugetc(msg) == '\r') || (ugetc(msg) == '\n'))
        msg += uwidth(msg);

    MessageBoxW(allegro_wnd,
                (unsigned short *)uconvert(msg, U_CURRENT, tmp1, U_UNICODE, ALLEGRO_MESSAGE_SIZE),
                (unsigned short *)uconvert(wnd_title, U_ASCII, tmp2, U_UNICODE, sizeof(tmp2)),
                MB_OK);

    _AL_FREE(tmp1);
}
예제 #3
0
파일: win.c 프로젝트: rj76/kq
/*! \brief Return the name of 'significant' directories.
 *
 * \param   dir Enumerated constant for directory type  \sa DATA_DIR et al.
 * \param   file File name below that directory.
 * \returns the combined path
 */
const char *kqres (int dir, const char *file)
{
   HINSTANCE SHFolder;
   SHGETFOLDERPATH SHGetFolderPath;
   char *home;

   if (!init_path) {
	WCHAR tmp[PATH_MAX];
      home = NULL;
      /* Get home directory; this bit originally written by SH */
      SHFolder = LoadLibrary ("shfolder.dll");
      if (SHFolder != NULL) {
         SHGetFolderPath =
            (void *) GetProcAddress (SHFolder, "SHGetFolderPathW");
         if (SHGetFolderPath != NULL) {
            /* Get the "Application Data" folder for the current user */
            if (SHGetFolderPath
                (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL,
                 SHGFP_TYPE_CURRENT, tmp) = S_OK) {
				home = uconvert(tmp, U_UNICODE, NULL, U_UTF8, 0);
			   }
         }
         FreeLibrary (SHFolder);
      }

      /* Do not get fooled by a corrupted $HOME */
      if (home != NULL && strlen (home) < PATH_MAX) {
         sprintf (user_dir, "%s\\KQ", home);
         /* Always try to make the directory, just to be sure. */
         mkdir (user_dir);
      } else {
         strcpy (user_dir, ".");
      }
      /* Now the data directory */
      strcpy (game_dir, ".");
      init_path = 1;
   }

   switch (dir) {
   case DATA_DIR:
      return get_resource_file_path(game_dir, "data", file);
      break;
   case MUSIC_DIR:
  	   return get_resource_file_path(game_dir, "music", file);
      break;
   case MAP_DIR:
  	   return get_resource_file_path(game_dir, "maps", file);
      break;
   case SAVE_DIR:
   case SETTINGS_DIR:
  	   return get_resource_file_path(user_dir, "", file);
      break;
   case SCRIPT_DIR:
  	   return get_lua_file_path(file);
      break;
   default:
      return NULL;
   }
}
예제 #4
0
extern "C" void be_sys_message(AL_CONST char *msg)
{
    char  filename[MAXPATHLEN];
    char *title;
    char  tmp[ALLEGRO_MESSAGE_SIZE];
    char  tmp2[ALLEGRO_MESSAGE_SIZE];

    get_executable_name(filename, sizeof(filename));
    title = get_filename(filename);

    BAlert *alert = new BAlert(title,
                               uconvert(msg, U_CURRENT, tmp, U_UTF8, ALLEGRO_MESSAGE_SIZE),
                               uconvert(get_config_text("Ok"), U_CURRENT, tmp2, U_UTF8, ALLEGRO_MESSAGE_SIZE));
    alert->SetShortcut(0, B_ESCAPE);
    be_app->ShowCursor();
    alert->Go();
    be_app->HideCursor();
}
예제 #5
0
파일: wfile.c 프로젝트: Skiles/aseprite
/* _al_file_time:
 *  Returns the timestamp of the specified file.
 */
time_t _al_file_time(AL_CONST char *filename)
{
   struct _stat s;
   char tmp[1024];

   if (get_filename_encoding() != U_UNICODE) {
      if (_stat(uconvert(filename, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &s) != 0) {
         *allegro_errno = errno;
         return 0;
      }
   }
   else {
      if (_wstat((wchar_t*)uconvert(filename, U_CURRENT, tmp, U_UNICODE, sizeof(tmp)), &s) != 0) {
         *allegro_errno = errno;
         return 0;
      }
   }

   return s.st_mtime;
}
예제 #6
0
/* _al_file_time:
 *  Returns the timestamp of the specified file.
 */
time_t _al_file_time(AL_CONST char *filename)
{
   struct stat s;
   char tmp[1024];

   if (stat(uconvert(filename, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) != 0) {
      *allegro_errno = errno;
      return 0;
   }

   return s.st_mtime;
}
예제 #7
0
/* _al_file_size_ex:
 *  Measures the size of the specified file.
 */
uint64_t _al_file_size_ex(AL_CONST char *filename)
{
   struct _stat s;
   char tmp[1024];

   if (!_al_win_unicode_filenames) {
      if (_stat(uconvert(filename, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &s) != 0) {
         *allegro_errno = errno;
         return 0;
      }
   }
   else {
      if (_wstat((wchar_t*)uconvert(filename, U_CURRENT, tmp, U_UNICODE,
                 sizeof(tmp)), &s) != 0) {
         *allegro_errno = errno;
         return 0;
      }
   }

   return s.st_size;
}
예제 #8
0
int eof_system(const char * command)
{
	#ifdef ALLEGRO_WINDOWS
		wchar_t wcommand[1024] = {0};

		if(command == NULL)
			return -1;
		(void) uconvert(command, U_UTF8, (char *)(&wcommand[0]), U_UNICODE, 2048);
		return _wsystem(wcommand);
	#else
		if(command == NULL)
			return -1;
		return system(command);
	#endif
}
예제 #9
0
int eof_mkdir(const char * dir)
{
	#ifdef ALLEGRO_WINDOWS
		wchar_t wdir[1024] = {0};

		if(dir == NULL)
			return -1;
		(void) uconvert(dir, U_UTF8, (char *)(&wdir[0]), U_UNICODE, 2048);
		return _wmkdir(wdir);
	#else
		if(dir == NULL)
			return -1;
		return mkdir(dir, 0777);
	#endif
}
예제 #10
0
/* _xwin_sysdrv_message:
 *  Displays a message. Uses xmessage if possible, and stdout if not.
 */
static void _xwin_sysdrv_message(AL_CONST char *msg)
{
   char buf[ALLEGRO_MESSAGE_SIZE+1];
   char *msg2;
   size_t len;
   pid_t pid;
   int status;

   /* convert message to ASCII */
   msg2 = uconvert(msg, U_CURRENT, buf, U_ASCII, ALLEGRO_MESSAGE_SIZE);

   /* xmessage interprets some strings beginning with '-' as command-line
    * options. To avoid this we make sure all strings we pass to it have
    * newlines on the end. This is also useful for the fputs() case.
    */
   len = strlen(msg2);
   ASSERT(len < ALLEGRO_MESSAGE_SIZE);
   if ((len == 0) || (msg2[len-1] != '\n'))
      strcat(msg2, "\n");

   /* fork a child */
   pid = fork();
   switch (pid) {

      case -1: /* fork error */
         fputs(msg2, stdout);
         break;

      case 0: /* child process */
         execlp("xmessage", "xmessage", "-buttons", "OK:101", "-default", "OK", "-center", msg2, (char *)NULL);

         /* if execution reaches here, it means execlp failed */
         _exit(EXIT_FAILURE);
         break;

      default: /* parent process */
         waitpid(pid, &status, 0);
         if ((!WIFEXITED(status))
             || (WEXITSTATUS(status) != 101)) /* ok button */
         {
            fputs(msg2, stdout);
         }

         break;
   }
}
예제 #11
0
/* sys_linux_message:
 *  Display a message on our original console.
 */
static void sys_linux_message (const char *msg)
{
   char *tmp;
   int ret;
   ASSERT(msg);

   tmp = al_malloc(ALLEGRO_MESSAGE_SIZE);
   msg = uconvert(msg, U_UTF8, tmp, U_ASCII, ALLEGRO_MESSAGE_SIZE);

   do {
      ret = write(STDERR_FILENO, msg, strlen(msg));
      if ((ret < 0) && (errno != EINTR))
	 break;
   } while (ret < (int)strlen(msg));

   __al_linux_got_text_message = true;

   al_free(tmp);
}
예제 #12
0
파일: wkeybd.c 프로젝트: Aquilon96/ags
/* scancode_to_name:
 *  Converts the given scancode to a description of the key.
 */
static AL_CONST char *key_directx_scancode_to_name(const int scancode)
{
   static char name[256];
   TCHAR str[256];
   WCHAR wstr[256];

   ASSERT(scancode >= 0 && scancode < KEY_MAX);

   if (GetKeyNameText(reverse_mapping[scancode], str, sizeof str)) {
      /* let Windows translate from the current encoding into UTF16 */
      MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr);
      /* translate from utf16 to Allegro's current encoding */
      uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name);
      /* why oh why doesn't everybody just use UTF8/16 */
      return name;
   }
   else
      return _keyboard_common_names[scancode];
}
예제 #13
0
/* directx_wnd_proc:
 *  Window procedure for the Allegro window class.
 */
static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
{
   PAINTSTRUCT ps;

   if (message == msg_call_proc)
      return ((int (*)(void))wparam) ();

   if (message == msg_suicide) {
      DestroyWindow(wnd);
      return 0;
   }

   /* See get_reverse_mapping() in wkeybd.c to see what this is for. */
   if (FALSE && (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)) {
      static char name[256];
      TCHAR str[256];
      WCHAR wstr[256];

      GetKeyNameText(lparam, str, sizeof str);
      MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr);
      uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name);
      _TRACE(PREFIX_I" key[%s] = 0x%08lx;\n", name, lparam & 0x1ff0000);
   }

   switch (message) {

      case WM_CREATE:
         if (!user_wnd_proc)
            allegro_wnd = wnd;
         break;

      case WM_DESTROY:
         if (user_wnd_proc) {
            exit_window_modules(NULL);
            _win_reset_switch_mode();
         }
         else {
            PostQuitMessage(0);
         }

         allegro_wnd = NULL;
         break;

      case WM_SETCURSOR:
         if (!user_wnd_proc || _mouse_installed) {
            mouse_set_syscursor();
            return 1;  /* not TRUE */
         }
         break;

      case WM_ACTIVATE:
         if (LOWORD(wparam) == WA_INACTIVE) {
            _win_switch_out();
         }
         else {
	    /* Ignore the WM_ACTIVATE event if the window is minimized. */
	    if (HIWORD(wparam))
	       break;

            if (gfx_driver && !gfx_driver->windowed) {
               /* 1.2s delay to let Windows complete the switch in fullscreen mode */
               SetTimer(allegro_wnd, SWITCH_TIMER, 1200, NULL);
            }
            else {
               /* no delay in windowed mode */
               _win_switch_in();
            }
         }
         break;

      case WM_TIMER:
         if (wparam == SWITCH_TIMER) {
            KillTimer(allegro_wnd, SWITCH_TIMER);
            _win_switch_in();
            return 0;
         }
         break;

      case WM_ENTERSIZEMOVE:
         if (win_gfx_driver && win_gfx_driver->enter_sysmode)
            win_gfx_driver->enter_sysmode();
         break;

      case WM_EXITSIZEMOVE:
         if (win_gfx_driver && win_gfx_driver->exit_sysmode)
            win_gfx_driver->exit_sysmode();
         break;

      case WM_MOVE:
         if (GetActiveWindow() == allegro_wnd) {
            if (!IsIconic(allegro_wnd)) {
               wnd_x = (short) LOWORD(lparam);
               wnd_y = (short) HIWORD(lparam);

               if (win_gfx_driver && win_gfx_driver->move)
                  win_gfx_driver->move(wnd_x, wnd_y, wnd_width, wnd_height);
            }
            else if (win_gfx_driver && win_gfx_driver->iconify) {
               win_gfx_driver->iconify();
            }
         }
         break;

      case WM_SIZE:
         wnd_width = LOWORD(lparam);
         wnd_height = HIWORD(lparam);
         break;

      case WM_PAINT:
         if (!user_wnd_proc || win_gfx_driver) {
            BeginPaint(wnd, &ps);
            if (win_gfx_driver && win_gfx_driver->paint)
                win_gfx_driver->paint(&ps.rcPaint);
            EndPaint(wnd, &ps);
            return 0;
         }
         break;

      case WM_KEYDOWN:
      case WM_KEYUP:
      case WM_SYSKEYDOWN:
      case WM_SYSKEYUP:
         /* Disable the default message-based key handler
          * in order to prevent conflicts on NT kernels.
          */
         if (!user_wnd_proc || _keyboard_installed)
            return 0;
         break;

      case WM_SYSCOMMAND:
         if (wparam == SC_MONITORPOWER || wparam == SC_SCREENSAVE) {
            if (_screensaver_policy == ALWAYS_DISABLED
                || (_screensaver_policy == FULLSCREEN_DISABLED
                    && gfx_driver && !gfx_driver->windowed))
            return 0;
         }
         break;

      case WM_INITMENUPOPUP:
         wnd_sysmenu = TRUE;
         mouse_set_sysmenu(TRUE);

         if (win_gfx_driver && win_gfx_driver->enter_sysmode)
            win_gfx_driver->enter_sysmode();
         break;

      case WM_MENUSELECT:
         if ((HIWORD(wparam) == 0xFFFF) && (!lparam)) {
            wnd_sysmenu = FALSE;
            mouse_set_sysmenu(FALSE);

            if (win_gfx_driver && win_gfx_driver->exit_sysmode)
               win_gfx_driver->exit_sysmode();
         }
         break;

      case WM_MENUCHAR :
         return (MNC_CLOSE<<16)|(wparam&0xffff);
         
      case WM_CLOSE:
         if (!user_wnd_proc) {
            if (user_close_proc)
               (*user_close_proc)();
            return 0;
         }
         break;
   }

   /* pass message to default window proc */
   if (user_wnd_proc)
      return CallWindowProc(user_wnd_proc, wnd, message, wparam, lparam);
   else
      return DefWindowProc(wnd, message, wparam, lparam);
}
예제 #14
0
/* al_findfirst:
 *  Initiates a directory search.
 */
int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib)
{
   struct FF_DATA *ff_data;
   struct stat s;
   int actual_attrib;
   char tmp[1024];
   char *p;

   /* allocate ff_data structure */
   ff_data = _AL_MALLOC(sizeof(struct FF_DATA));
   if (!ff_data) {
      *allegro_errno = ENOMEM;
      return -1;
   }

   memset(ff_data, 0, sizeof *ff_data);
   info->ff_data = (void *) ff_data;

   /* if the pattern contains no wildcard, we use stat() */
   if (!ustrpbrk(pattern, uconvert("?*", U_ASCII, tmp, U_CURRENT, sizeof(tmp)))) {
      /* start the search */
      errno = *allegro_errno = 0;

      if (stat(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) == 0) {
         /* get file attributes */
         actual_attrib = ff_get_attrib(ff_get_filename(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp))), &s);

         /* does it match ? */
         if ((actual_attrib & ~attrib) == 0) {
            info->attrib = actual_attrib;
            info->time = s.st_mtime;
            info->size = s.st_size; /* overflows at 2GB */
            ff_data->size = s.st_size;
            ustrzcpy(info->name, sizeof(info->name), get_filename(pattern));
            return 0;
         }
      }

       _AL_FREE(ff_data);
      info->ff_data = NULL;
      *allegro_errno = (errno ? errno : ENOENT);
      return -1;
   }

   ff_data->attrib = attrib;

   do_uconvert(pattern, U_CURRENT, ff_data->dirname, U_UTF8, sizeof(ff_data->dirname));
   p = ff_get_filename(ff_data->dirname);
   _al_sane_strncpy(ff_data->pattern, p, sizeof(ff_data->pattern));
   if (p == ff_data->dirname)
      _al_sane_strncpy(ff_data->dirname, "./", FF_MAXPATHLEN);
   else
      *p = 0;

   /* nasty bodge, but gives better compatibility with DOS programs */
   if (strcmp(ff_data->pattern, "*.*") == 0)
      _al_sane_strncpy(ff_data->pattern, "*", FF_MAXPATHLEN);

   /* start the search */
   errno = *allegro_errno = 0;

   ff_data->dir = opendir(ff_data->dirname);

   if (!ff_data->dir) {
      *allegro_errno = (errno ? errno : ENOENT);
      _AL_FREE(ff_data);
      info->ff_data = NULL;
      return -1;
   }

   if (al_findnext(info) != 0) {
      al_findclose(info);
      return -1;
   }

   return 0;
}
예제 #15
0
파일: wfile.c 프로젝트: Skiles/aseprite
/* al_findfirst:
 *  Initiates a directory search.
 */
int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib)
{
   struct FF_DATA *ff_data;
   char tmp[1024];

   /* allocate ff_data structure */
   ff_data = _AL_MALLOC(sizeof(struct FF_DATA));

   if (!ff_data) {
      *allegro_errno = ENOMEM;
      return -1;
   }

   /* attach it to the info structure */
   info->ff_data = (void *) ff_data;

   /* Windows defines specific flags for NTFS permissions:
    *   FA_TEMPORARY            0x0100
    *   FA_SPARSE_FILE          0x0200 
    *   FA_REPARSE_POINT        0x0400
    *   FA_COMPRESSED           0x0800
    *   FA_OFFLINE              0x1000
    *   FA_NOT_CONTENT_INDEXED  0x2000
    *   FA_ENCRYPTED            0x4000
    * so we must set them in the mask by default; moreover,
    * in order to avoid problems with flags added in the
    * future, we simply set all bits past the first byte.
    */
   ff_data->attrib = attrib | 0xFFFFFF00;

   /* start the search */
   errno = *allegro_errno = 0;

   if (get_filename_encoding() != U_UNICODE) {
      ff_data->handle = _findfirst(uconvert(pattern, U_CURRENT, tmp,
                                            U_ASCII, sizeof(tmp)),
                                            &ff_data->data.a);

      if (ff_data->handle < 0) {
         *allegro_errno = errno;
         _AL_FREE(ff_data);
         info->ff_data = NULL;
         return -1;
      }

      if (ff_data->data.a.attrib & ~ff_data->attrib) {
         if (al_findnext(info) != 0) {
            al_findclose(info);
            return -1;
         }
         else
            return 0;
      }
   }
   else {
      ff_data->handle = _wfindfirst((wchar_t*)uconvert(pattern, U_CURRENT, tmp,
                                                       U_UNICODE, sizeof(tmp)),
                                                       &ff_data->data.w);

      if (ff_data->handle < 0) {
         *allegro_errno = errno;
         _AL_FREE(ff_data);
         info->ff_data = NULL;
         return -1;
      }

      if (ff_data->data.w.attrib & ~ff_data->attrib) {
         if (al_findnext(info) != 0) {
            al_findclose(info);
            return -1;
         }
         else
            return 0;
      }
   }

   fill_ffblk(info);
   return 0;
}
예제 #16
0
파일: xkeyboard.c 프로젝트: Skiles/aseprite
/* _xwin_keyboard_handler:
 *  Keyboard "interrupt" handler.
 */
void _xwin_keyboard_handler(XKeyEvent *event, int dga2_hack)
{
   int keycode;

   if (!xkeyboard_installed)
      return;

   if (_xwin_keyboard_callback)
      (*_xwin_keyboard_callback)(event->type == KeyPress ? 1 : 0, event->keycode);

   keycode = _xwin.keycode_to_scancode[event->keycode];
   if (keycode == -1)
      keycode = find_unknown_key_assignment(event->keycode);

   if (dga2_hack)
      dga2_update_shifts(event);
   else
      update_shifts(event);

   /* Special case the pause key. */
   if (keycode == KEY_PAUSE) {
      /* Allegro ignore's releasing of the pause key. */
      if (event->type == KeyRelease)
         return;
      if (pause_key) {
         event->type = KeyRelease;
         pause_key = 0;
      }
      else {
         pause_key = 1;
      }
   }

   if (event->type == KeyPress) { /* Key pressed.  */
      int len;
      char buffer[16];
      char buffer2[16];
      int unicode = 0, r = 0;

#if defined (ALLEGRO_XWINDOWS_WITH_XIM) && defined(X_HAVE_UTF8_STRING)
      if (xic) {
	 len = Xutf8LookupString(xic, event, buffer, sizeof buffer, NULL, NULL);
      }
      else
#endif
      {
         /* XLookupString is supposed to only use ASCII. */
	 len = XLookupString(event, buffer, sizeof buffer, NULL, NULL);
      }
      buffer[len] = '\0';
      uconvert(buffer, U_UTF8, buffer2, U_UNICODE, sizeof buffer2);
      unicode = *(unsigned short *)buffer2;

#ifdef ALLEGRO_XWINDOWS_WITH_XIM
      r = XFilterEvent((XEvent *)event, _xwin.window);
#endif
      if (keycode || unicode) {
	 /* If we have a keycode, we want it to go to Allegro immediately, so the
	  * key[] array is updated, and the user callbacks are called. OTOH, a key
	  * should not be added to the keyboard buffer (parameter -1) if it was
          * filtered out as a compose key, or if it is a modifier key.
	  */
	 if (r || keycode >= KEY_MODIFIERS)
	    unicode = -1;
	 else {
	    /* Historically, Allegro expects to get only the scancode when Alt is
	     * held down.
	     */
	    if (_key_shifts & KB_ALT_FLAG)
	       unicode = 0;
         }

	 _handle_key_press(unicode, keycode);

         /* Detect Ctrl-Alt-End. */
         if (keycode == KEY_END && (_key_shifts & KB_CTRL_FLAG) &&
            (_key_shifts & KB_ALT_FLAG) && (three_finger_flag))
         {
         #ifndef ALLEGRO_HAVE_LIBPTHREAD
            if (_unix_bg_man == &_bg_man_sigalrm) {
               _sigalrm_request_abort();
            }
            else
         #endif
            {
               TRACE(PREFIX_W "Three finger combo detected. SIGTERMing "
                     "pid %d\n", main_pid);
               kill(main_pid, SIGTERM);
            }
         }
      }
   }
   else { /* Key release. */
      _handle_key_release(keycode);
   }
}