コード例 #1
0
ファイル: w32notify.c プロジェクト: Ferryworld/emacs
/* Stop watching a directory specified by a pointer to its dirwatch object.  */
static int
remove_watch (struct notification *dirwatch)
{
  if (dirwatch && dirwatch->signature == DIRWATCH_SIGNATURE)
    {
      int i;
      BOOL status;
      DWORD exit_code = 0, err = 0;

      /* Only the thread that issued the outstanding I/O call can call
	 CancelIo on it.  (CancelIoEx is available only since Vista.)
	 So we need to queue an APC for the worker thread telling it
	 to terminate.  */
      if (!QueueUserAPC (watch_end, dirwatch->thr, (ULONG_PTR)dirwatch->dir))
	DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ()));

      /* We also signal the thread that it can terminate.  */
      SetEvent(dirwatch->terminate);

      /* Wait for the thread to exit.  FIXME: is there a better method
	 that is not overly complex?  */
      for (i = 0; i < 50; i++)
	{
	  if (!((status = GetExitCodeThread (dirwatch->thr, &exit_code))
		&& exit_code == STILL_ACTIVE))
	    break;
	  Sleep (10);
	}

      if ((status == FALSE && (err = GetLastError ()) == ERROR_INVALID_HANDLE)
	  || exit_code == STILL_ACTIVE)
	{
	  if (!(status == FALSE && err == ERROR_INVALID_HANDLE))
	    {
              DebPrint(("Forcing thread termination.\n"));
	      TerminateThread (dirwatch->thr, 0);
	      if (dirwatch->dir)
		CloseHandle (dirwatch->dir);
	    }
	}

      /* Clean up.  */
      if (dirwatch->thr)
	{
	  CloseHandle (dirwatch->thr);
	  dirwatch->thr = NULL;
	}
      CloseHandle(dirwatch->terminate);
      xfree (dirwatch->buf);
      xfree (dirwatch->io_info);
      xfree (dirwatch->watchee);
      xfree (dirwatch);
      return 0;
    }
  else
    {
      DebPrint (("Unknown dirwatch object!\n"));
      return -1;
    }
}
コード例 #2
0
ファイル: w32notify.c プロジェクト: maxgfaraday/emacs
/* Stop watching a directory specified by a pointer to its dirwatch object.  */
static int
remove_watch (struct notification *dirwatch)
{
  if (dirwatch && dirwatch->signature == DIRWATCH_SIGNATURE)
    {
      int i;
      BOOL status;
      DWORD exit_code, err;

      /* Only the thread that issued the outstanding I/O call can call
	 CancelIo on it.  (CancelIoEx is available only since Vista.)
	 So we need to queue an APC for the worker thread telling it
	 to terminate.  */
      if (!QueueUserAPC (watch_end, dirwatch->thr, (ULONG_PTR)dirwatch->dir))
	DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ()));
      /* We also set the terminate flag, for when the thread is
	 waiting on the critical section that never gets acquired.
	 FIXME: is there a cleaner method?  Using SleepEx there is a
	 no-no, as that will lead to recursive APC invocations and
	 stack overflow.  */
      dirwatch->terminate = 1;
      /* Wait for the thread to exit.  FIXME: is there a better method
	 that is not overly complex?  */
      for (i = 0; i < 50; i++)
	{
	  if (!((status = GetExitCodeThread (dirwatch->thr, &exit_code))
		&& exit_code == STILL_ACTIVE))
	    break;
	  Sleep (10);
	}
      if ((status == FALSE && (err = GetLastError ()) == ERROR_INVALID_HANDLE)
	  || exit_code == STILL_ACTIVE)
	{
	  if (!(status == FALSE && err == ERROR_INVALID_HANDLE))
	    {
	      TerminateThread (dirwatch->thr, 0);
	      if (dirwatch->dir)
		CloseHandle (dirwatch->dir);
	    }
	}

      /* Clean up.  */
      if (dirwatch->thr)
	{
	  CloseHandle (dirwatch->thr);
	  dirwatch->thr = NULL;
	}
      xfree (dirwatch->buf);
      xfree (dirwatch->io_info);
      xfree (dirwatch->watchee);
      xfree (dirwatch);

      return 0;
    }
  else
    {
      DebPrint (("Unknown dirwatch object!\n"));
      return -1;
    }
}
コード例 #3
0
ファイル: w32menu.c プロジェクト: 0xAX/emacs
/* Free memory used by owner-drawn strings.  */
static void
w32_free_submenu_strings (HMENU menu)
{
  int i, num = GetMenuItemCount (menu);
  for (i = 0; i < num; i++)
    {
      MENUITEMINFO info;
      memset (&info, 0, sizeof (info));
      info.cbSize = sizeof (info);
      info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;

      get_menu_item_info (menu, i, TRUE, &info);

      /* Owner-drawn names are held in dwItemData.  */
      if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
	{
#ifdef MENU_DEBUG
	  DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
#endif
	  local_free (info.dwItemData);
	}

      /* Recurse down submenus.  */
      if (info.hSubMenu)
	w32_free_submenu_strings (info.hSubMenu);
    }
}
コード例 #4
0
ファイル: w32heap.c プロジェクト: dkogan/emacs-snapshot
void
mmap_free (void **var)
{
  if (*var)
    {
      if (VirtualFree (*var, 0, MEM_RELEASE) == 0)
        DebPrint (("mmap_free: error %ld\n", GetLastError ()));
      *var = NULL;
    }
}
コード例 #5
0
ファイル: GameWorld.cpp プロジェクト: ehershey/development
objID cGameWorld::GetGoodSpawnEnt()
{
    /**
     * Step through the list of spawn ents.
     * choose the one that is farthest from
     * the rest of the players.
     */
    list< cGamePlayerEnt* > players;
    ListPlayers( &players );

    DebPrint( "found %d players", players.size() );

    int nSpawnEnts = m_spawnEnts.size();
    int best=0;
    float bestDist = 0.f;

    for( int i=0; i<nSpawnEnts; i++ )
    {
        cGameEnt* pEnt = (cGameEnt*)MsgDaemon()->Get( m_spawnEnts[i] );

        if( !pEnt )
        {
            LogPrint("cGameWorld::GetGoodSpawnEnt: bad ID");
            return -1;
        }


        list< cGamePlayerEnt* >::iterator iter;
        float bestCurrDist = 10000.f;
        for( iter = players.begin(); iter != players.end(); iter++ )
        {
            float currDist = point3::Dist( (*iter)->GetLoc(), pEnt->GetLoc() );
            if( currDist < bestCurrDist )
            {
                bestCurrDist = currDist;
            }
        }
        // If this is the new best one, take it.
        if( bestCurrDist > bestDist )
        {
            best = i;
            bestDist = bestCurrDist;
        }

    }
    // return the best one.
    return m_spawnEnts[ best ];
}
コード例 #6
0
ファイル: w32heap.c プロジェクト: dkogan/emacs-snapshot
void *
mmap_alloc (void **var, size_t nbytes)
{
  void *p = NULL;

  /* We implement amortized allocation.  We start by reserving twice
     the size requested and commit only the size requested.  Then
     realloc could proceed and use the reserved pages, reallocating
     only if needed.  Buffer shrink would happen only so that we stay
     in the 2x range.  This is a big win when visiting compressed
     files, where the final size of the buffer is not known in
     advance, and the buffer is enlarged several times as the data is
     decompressed on the fly.  */
  if (nbytes < MAX_BUFFER_SIZE)
    p = VirtualAlloc (NULL, ROUND_UP (nbytes * 2, get_allocation_unit ()),
		      MEM_RESERVE, PAGE_READWRITE);

  /* If it fails, or if the request is above 512MB, try with the
     requested size.  */
  if (p == NULL)
    p = VirtualAlloc (NULL, ROUND_UP (nbytes, get_allocation_unit ()),
		      MEM_RESERVE, PAGE_READWRITE);

  if (p != NULL)
    {
      /* Now, commit pages for NBYTES.  */
      *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE);
      if (*var == NULL)
	p = *var;
    }

  if (!p)
    {
      DWORD e = GetLastError ();

      if (e == ERROR_NOT_ENOUGH_MEMORY)
	errno = ENOMEM;
      else
	{
	  DebPrint (("mmap_alloc: error %ld\n", e));
	  errno = EINVAL;
	}
    }

  return *var = p;
}
コード例 #7
0
ファイル: w32notify.c プロジェクト: Ferryworld/emacs
/* Worker routine for the watch thread.  */
static DWORD WINAPI
watch_worker (LPVOID arg)
{
  struct notification *dirwatch = (struct notification *)arg;
  BOOL bErr;
  DWORD _bytes = 0;
  DWORD status;

  if (dirwatch->dir)
    {
      bErr = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
				    DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
				    dirwatch->filter, &_bytes,
				    dirwatch->io_info, watch_completion);
      if (!bErr)
	{
	  DebPrint (("ReadDirectoryChangesW: %lu\n", GetLastError ()));
	  /* We cannot remove the dirwatch object from watch_list,
	     because we are in a separate thread.  For the same
	     reason, we also cannot free memory consumed by the
	     buffers allocated for the dirwatch object.  So we close
	     the directory handle, but do not free the object itself
	     or its buffers.  We also don't touch the signature.  This
	     way, remove_watch can still identify the object, remove
	     it, and free its memory.  */
	  CloseHandle (dirwatch->dir);
	  dirwatch->dir = NULL;
	  return 1;
	}
    }

  do {
    status = WaitForSingleObjectEx(dirwatch->terminate, INFINITE, TRUE);
  } while (status == WAIT_IO_COMPLETION);

  /* The thread is about to terminate, so we clean up the dir handle.  */
  CloseHandle (dirwatch->dir);
  dirwatch->dir = NULL;

  return 0;
}
コード例 #8
0
ファイル: w32notify.c プロジェクト: maxgfaraday/emacs
/* Worker routine for the watch thread.  */
static DWORD WINAPI
watch_worker (LPVOID arg)
{
  struct notification *dirwatch = (struct notification *)arg;

  do {
    BOOL status;
    DWORD sleep_result;
    DWORD bytes_ret = 0;

    if (dirwatch->dir)
      {
	status = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, 16384,
					dirwatch->subtree, dirwatch->filter,
					&bytes_ret,
					dirwatch->io_info, watch_completion);
	if (!status)
	  {
	    DebPrint (("watch_worker, abnormal exit: %lu\n", GetLastError ()));
	    /* We cannot remove the dirwatch object from watch_list,
	       because we are in a separate thread.  For the same
	       reason, we also cannot free memory consumed by the
	       buffers allocated for the dirwatch object.  So we close
	       the directory handle, but do not free the object itself
	       or its buffers.  We also don't touch the signature.
	       This way, remove_watch can still identify the object,
	       remove it, and free its memory.  */
	    CloseHandle (dirwatch->dir);
	    dirwatch->dir = NULL;
	    return 1;
	  }
      }
    /* Sleep indefinitely until awoken by the I/O completion, which
       could be either a change notification or a cancellation of the
       watch.  */
    sleep_result = SleepEx (INFINITE, TRUE);
  } while (!dirwatch->terminate);

  return 0;
}
コード例 #9
0
ファイル: w32inevt.c プロジェクト: exedre/emacs
/* return code -1 means that event_queue_ptr won't be incremented.
   In other word, this event makes two key codes.   (by himi)       */
static int
key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
{
  static int mod_key_state = 0;
  int wParam;

  *isdead = 0;

  /* Skip key-up events.  */
  if (!event->bKeyDown)
    {
      switch (event->wVirtualKeyCode)
	{
	case VK_LWIN:
	  mod_key_state &= ~LEFT_WIN_PRESSED;
	  break;
	case VK_RWIN:
	  mod_key_state &= ~RIGHT_WIN_PRESSED;
	  break;
	case VK_APPS:
	  mod_key_state &= ~APPS_PRESSED;
	  break;
	}
      return 0;
    }

  /* Ignore keystrokes we fake ourself; see below.  */
  if (faked_key == event->wVirtualKeyCode)
    {
      faked_key = 0;
      return 0;
    }

  /* To make it easier to debug this code, ignore modifier keys!  */
  switch (event->wVirtualKeyCode)
    {
    case VK_LWIN:
      if (NILP (Vw32_pass_lwindow_to_system))
	{
	  /* Prevent system from acting on keyup (which opens the Start
	     menu if no other key was pressed) by simulating a press of
	     Space which we will ignore.  */
	  if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
	    {
	      if (NUMBERP (Vw32_phantom_key_code))
		faked_key = XUINT (Vw32_phantom_key_code) & 255;
	      else
		faked_key = VK_SPACE;
	      keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
	    }
	}
      mod_key_state |= LEFT_WIN_PRESSED;
      if (!NILP (Vw32_lwindow_modifier))
	return 0;
      break;
    case VK_RWIN:
      if (NILP (Vw32_pass_rwindow_to_system))
	{
	  if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
	    {
	      if (NUMBERP (Vw32_phantom_key_code))
		faked_key = XUINT (Vw32_phantom_key_code) & 255;
	      else
		faked_key = VK_SPACE;
	      keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
	    }
	}
      mod_key_state |= RIGHT_WIN_PRESSED;
      if (!NILP (Vw32_rwindow_modifier))
	return 0;
      break;
    case VK_APPS:
      mod_key_state |= APPS_PRESSED;
      if (!NILP (Vw32_apps_modifier))
	return 0;
      break;
    case VK_CAPITAL:
      /* Decide whether to treat as modifier or function key.  */
      if (NILP (Vw32_enable_caps_lock))
	goto disable_lock_key;
      return 0;
    case VK_NUMLOCK:
      /* Decide whether to treat as modifier or function key.  */
      if (NILP (Vw32_enable_num_lock))
	goto disable_lock_key;
      return 0;
    case VK_SCROLL:
      /* Decide whether to treat as modifier or function key.  */
      if (NILP (Vw32_scroll_lock_modifier))
	goto disable_lock_key;
      return 0;
    disable_lock_key:
      /* Ensure the appropriate lock key state is off (and the
	 indicator light as well).  */
      wParam = event->wVirtualKeyCode;
      if (GetAsyncKeyState (wParam) & 0x8000)
	{
	  /* Fake another press of the relevant key.  Apparently, this
	     really is the only way to turn off the indicator.  */
	  faked_key = wParam;
	  keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
		       KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
	  keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
		       KEYEVENTF_EXTENDEDKEY | 0, 0);
	  keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
		       KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
	}
      break;
    case VK_MENU:
    case VK_CONTROL:
    case VK_SHIFT:
      return 0;
    case VK_CANCEL:
      /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
	 which is confusing for purposes of key binding; convert
	 VK_CANCEL events into VK_PAUSE events.  */
      event->wVirtualKeyCode = VK_PAUSE;
      break;
    case VK_PAUSE:
      /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
	 for purposes of key binding; convert these back into
	 VK_NUMLOCK events, at least when we want to see NumLock key
	 presses.  (Note that there is never any possibility that
	 VK_PAUSE with Ctrl really is C-Pause as per above.)  */
      if (NILP (Vw32_enable_num_lock)
	  && (event->dwControlKeyState
	      & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
	event->wVirtualKeyCode = VK_NUMLOCK;
      break;
    }

  /* Recognize state of Windows and Apps keys.  */
  event->dwControlKeyState |= mod_key_state;

  /* Distinguish numeric keypad keys from extended keys.  */
  event->wVirtualKeyCode =
    map_keypad_keys (event->wVirtualKeyCode,
		     (event->dwControlKeyState & ENHANCED_KEY));

  if (lispy_function_keys[event->wVirtualKeyCode] == 0)
    {
      if (!NILP (Vw32_recognize_altgr)
	  && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
	  && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
	{
	  /* Don't try to interpret AltGr key chords; ToAscii seems not
	     to process them correctly.  */
	}
      /* Handle key chords including any modifiers other than shift
         directly, in order to preserve as much modifier information as
         possible.  */
      else if (event->dwControlKeyState
	       & (  RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
		  | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
		  | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
		  | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
		  | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
		  | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
	{
	  /* Don't translate modified alphabetic keystrokes, so the user
	     doesn't need to constantly switch layout to type control or
	     meta keystrokes when the normal layout translates
	     alphabetic characters to non-ascii characters.  */
	  if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
	    {
	      event->uChar.AsciiChar = event->wVirtualKeyCode;
	      if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
		event->uChar.AsciiChar += ('a' - 'A');
	    }
	  /* Try to handle unrecognized keystrokes by determining the
             base character (ie. translating the base key plus shift
             modifier).  */
	  else if (event->uChar.AsciiChar == 0)
	    w32_kbd_patch_key (event, -1);
	}

      if (event->uChar.AsciiChar == 0)
	{
	  emacs_ev->kind = NO_EVENT;
	  return 0;
	}
      else if (event->uChar.AsciiChar > 0)
	{
	  /* Pure ASCII characters < 128.  */
	  emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
	  emacs_ev->code = event->uChar.AsciiChar;
	}
      else if (event->uChar.UnicodeChar > 0
	       && w32_console_unicode_input)
	{
	  /* Unicode codepoint; only valid if we are using Unicode
	     console input mode.  */
	  emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
	  emacs_ev->code = event->uChar.UnicodeChar;
	}
      else
	{
	  /* Fallback handling of non-ASCII characters for non-Unicode
	     versions of Windows, and for non-Unicode input on NT
	     family of Windows.  Only characters in the current
	     console codepage are supported by this fallback.  */
	  wchar_t code;
	  char dbcs[2];
          int cpId;

	  /* Get the current console input codepage to interpret this
	     key with.  Note that the system defaults for the OEM
	     codepage could have been changed by calling SetConsoleCP
	     or w32-set-console-codepage, so using GetLocaleInfo to
	     get LOCALE_IDEFAULTCODEPAGE is not TRT here.  */
          cpId = GetConsoleCP ();

	  dbcs[0] = dbcs_lead;
	  dbcs[1] = event->uChar.AsciiChar;
	  if (dbcs_lead)
	    {
	      dbcs_lead = 0;
	      if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
		{
		  /* Garbage  */
		  DebPrint (("Invalid DBCS sequence: %d %d\n",
			     dbcs[0], dbcs[1]));
		  emacs_ev->kind = NO_EVENT;
		}
	    }
	  else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
	    {
	      dbcs_lead = dbcs[1];
	      emacs_ev->kind = NO_EVENT;
	    }
	  else
	    {
	      if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
		{
		  /* Garbage  */
		  DebPrint (("Invalid character: %d\n", dbcs[1]));
		  emacs_ev->kind = NO_EVENT;
		}
	    }
	  emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
	  emacs_ev->code = code;
	}
    }
  else
    {
      /* Function keys and other non-character keys.  */
      emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
      emacs_ev->code = event->wVirtualKeyCode;
    }

  XSETFRAME (emacs_ev->frame_or_window, get_frame ());
  emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
					       event->wVirtualKeyCode);
  emacs_ev->timestamp = GetTickCount ();
  return 1;
}
コード例 #10
0
ファイル: w32heap.c プロジェクト: dkogan/emacs-snapshot
void *
mmap_realloc (void **var, size_t nbytes)
{
  MEMORY_BASIC_INFORMATION memInfo, m2;
  void *old_ptr;

  if (*var == NULL)
    return mmap_alloc (var, nbytes);

  /* This case happens in init_buffer().  */
  if (nbytes == 0)
    {
      mmap_free (var);
      return mmap_alloc (var, nbytes);
    }

  memset (&memInfo, 0, sizeof (memInfo));
  if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0)
    DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ()));

  /* We need to enlarge the block.  */
  if (memInfo.RegionSize < nbytes)
    {
      memset (&m2, 0, sizeof (m2));
      if (VirtualQuery ((char *)*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0)
        DebPrint (("mmap_realloc: VirtualQuery error = %ld\n",
		   GetLastError ()));
      /* If there is enough room in the current reserved area, then
	 commit more pages as needed.  */
      if (m2.State == MEM_RESERVE
	  && m2.AllocationBase == memInfo.AllocationBase
	  && nbytes <= memInfo.RegionSize + m2.RegionSize)
	{
	  void *p;

	  p = VirtualAlloc (*var, nbytes, MEM_COMMIT, PAGE_READWRITE);
	  if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */)
	    {
	      DebPrint (("realloc enlarge: VirtualAlloc (%p + %I64x, %I64x) error %ld\n",
			 *var, (uint64_t)memInfo.RegionSize,
			 (uint64_t)(nbytes - memInfo.RegionSize),
			 GetLastError ()));
	      DebPrint (("next region: %p %p %I64x %x\n", m2.BaseAddress,
			 m2.AllocationBase, (uint64_t)m2.RegionSize,
			 m2.AllocationProtect));
	    }
	  else
	    return *var;
	}
      /* Else we must actually enlarge the block by allocating a new
	 one and copying previous contents from the old to the new one.  */
      old_ptr = *var;

      if (mmap_alloc (var, nbytes))
	{
	  CopyMemory (*var, old_ptr, memInfo.RegionSize);
	  mmap_free (&old_ptr);
	  return *var;
	}
      else
	{
	  /* We failed to reallocate the buffer.  */
	  *var = old_ptr;
	  return NULL;
	}
    }

  /* If we are shrinking by more than one page...  */
  if (memInfo.RegionSize  > nbytes + getpagesize())
    {
      /* If we are shrinking a lot...  */
      if ((memInfo.RegionSize / 2) > nbytes)
        {
          /* Let's give some memory back to the system and release
	     some pages.  */
          old_ptr = *var;

	  if (mmap_alloc (var, nbytes))
            {
              CopyMemory (*var, old_ptr, nbytes);
              mmap_free (&old_ptr);
              return *var;
            }
          else
	    {
	      /* In case we fail to shrink, try to go on with the old block.
		 But that means there is a lot of memory pressure.
		 We could also decommit pages.  */
	      *var = old_ptr;
	      return *var;
	    }
        }

      /* We still can decommit pages.  */
      if (VirtualFree ((char *)*var + nbytes + get_page_size(),
		       memInfo.RegionSize - nbytes - get_page_size(),
		       MEM_DECOMMIT) == 0)
        DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError ()));
      return *var;
    }

  /* Not enlarging, not shrinking by more than one page.  */
  return *var;
}
コード例 #11
0
ファイル: w32heap.c プロジェクト: dkogan/emacs-snapshot
void
init_heap (bool use_dynamic_heap)
{
  /* FIXME: Remove the condition, the 'else' branch below, and all the
     related definitions and code, including dumped_data[], when unexec
     support is removed from Emacs.  */
  if (use_dynamic_heap)
    {
      /* After dumping, use a new private heap.  We explicitly enable
         the low fragmentation heap (LFH) here, for the sake of pre
         Vista versions.  Note: this will harmlessly fail on Vista and
         later, where the low-fragmentation heap is enabled by
         default.  It will also fail on pre-Vista versions when Emacs
         is run under a debugger; set _NO_DEBUG_HEAP=1 in the
         environment before starting GDB to get low fragmentation heap
         on XP and older systems, for the price of losing "certain
         heap debug options"; for the details see
         http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx.  */
      data_region_end = data_region_base;

      /* Create the private heap.  */
      heap = HeapCreate (0, 0, 0);

#ifndef MINGW_W64
      unsigned long enable_lfh = 2;
      /* Set the low-fragmentation heap for OS before Vista.  */
      HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
      HeapSetInformation_Proc s_pfn_Heap_Set_Information =
        (HeapSetInformation_Proc) get_proc_addr (hm_kernel32dll,
                                                        "HeapSetInformation");
      if (s_pfn_Heap_Set_Information != NULL)
	{
	  if (s_pfn_Heap_Set_Information ((PVOID) heap,
					  HeapCompatibilityInformation,
					  &enable_lfh, sizeof(enable_lfh)) == 0)
	    DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n",
		       GetLastError ()));
	}
#endif

      if (os_subtype == OS_9X)
        {
          the_malloc_fn = malloc_after_dump_9x;
          the_realloc_fn = realloc_after_dump_9x;
          the_free_fn = free_after_dump_9x;
        }
      else
        {
          the_malloc_fn = malloc_after_dump;
          the_realloc_fn = realloc_after_dump;
          the_free_fn = free_after_dump;
        }
    }
  else	/* Before dumping with unexec: use static heap.  */
    {
      /* Find the RtlCreateHeap function.  Headers for this function
         are provided with the w32 DDK, but the function is available
         in ntdll.dll since XP.  */
      HMODULE hm_ntdll = LoadLibrary ("ntdll.dll");
      RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap
	= (RtlCreateHeap_Proc) get_proc_addr (hm_ntdll, "RtlCreateHeap");
      /* Specific parameters for the private heap.  */
      RTL_HEAP_PARAMETERS params;
      ZeroMemory (&params, sizeof(params));
      params.Length = sizeof(RTL_HEAP_PARAMETERS);

      data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000);
      data_region_end = bc_limit = dumped_data + DUMPED_HEAP_SIZE;

      params.InitialCommit = committed = 0x1000;
      params.InitialReserve = sizeof(dumped_data);
      /* Use our own routine to commit memory from the dumped_data
         array.  */
      params.CommitRoutine = &dumped_data_commit;

      /* Create the private heap.  */
      if (s_pfn_Rtl_Create_Heap == NULL)
	{
	  fprintf (stderr, "Cannot build Emacs without RtlCreateHeap being available; exiting.\n");
	  exit (-1);
	}
      heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, &params);

      if (os_subtype == OS_9X)
        {
          fprintf (stderr, "Cannot dump Emacs on Windows 9X; exiting.\n");
          exit (-1);
        }
      else
        {
          the_malloc_fn = malloc_before_dump;
          the_realloc_fn = realloc_before_dump;
          the_free_fn = free_before_dump;
        }
    }

  /* Update system version information to match current system.  */
  cache_system_info ();
}
コード例 #12
0
ファイル: w32menu.c プロジェクト: 0xAX/emacs
static int
add_menu_item (HMENU menu, widget_value *wv, HMENU item)
{
  UINT fuFlags;
  char *out_string, *p, *q;
  int return_value;
  size_t nlen, orig_len;
  USE_SAFE_ALLOCA;

  if (menu_separator_name_p (wv->name))
    {
      fuFlags = MF_SEPARATOR;
      out_string = NULL;
    }
  else
    {
      if (wv->enabled)
	fuFlags = MF_STRING;
      else
	fuFlags = MF_STRING | MF_GRAYED;

      if (wv->key != NULL)
	{
	  out_string = SAFE_ALLOCA (strlen (wv->name) + strlen (wv->key) + 2);
	  p = stpcpy (out_string, wv->name);
	  p = stpcpy (p, "\t");
	  strcpy (p, wv->key);
	}
      else
	out_string = (char *)wv->name;

      /* Quote any special characters within the menu item's text and
	 key binding.  */
      nlen = orig_len = strlen (out_string);
      if (unicode_append_menu)
        {
          /* With UTF-8, & cannot be part of a multibyte character.  */
          for (p = out_string; *p; p++)
            {
              if (*p == '&')
                nlen++;
            }
        }
#ifndef NTGUI_UNICODE
      else
        {
          /* If encoded with the system codepage, use multibyte string
             functions in case of multibyte characters that contain '&'.  */
          for (p = out_string; *p; p = _mbsinc (p))
            {
              if (_mbsnextc (p) == '&')
                nlen++;
            }
        }
#endif /* !NTGUI_UNICODE */

      if (nlen > orig_len)
        {
          p = out_string;
          out_string = SAFE_ALLOCA (nlen + 1);
          q = out_string;
          while (*p)
            {
              if (unicode_append_menu)
                {
                  if (*p == '&')
                    *q++ = *p;
                  *q++ = *p++;
                }
#ifndef NTGUI_UNICODE
              else
                {
                  if (_mbsnextc (p) == '&')
                    {
                      _mbsncpy (q, p, 1);
                      q = _mbsinc (q);
                    }
                  _mbsncpy (q, p, 1);
                  p = _mbsinc (p);
                  q = _mbsinc (q);
                }
#endif /* !NTGUI_UNICODE */
            }
          *q = '\0';
        }

      if (item != NULL)
	fuFlags = MF_POPUP;
      else if (wv->title || wv->call_data == 0)
	{
	  /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
	     we can't deallocate the memory otherwise.  */
	  if (get_menu_item_info)
	    {
              out_string = (char *) local_alloc (strlen (wv->name) + 1);
              strcpy (out_string, wv->name);
#ifdef MENU_DEBUG
	      DebPrint ("Menu: allocating %ld for owner-draw", out_string);
#endif
	      fuFlags = MF_OWNERDRAW | MF_DISABLED;
	    }
	  else
	    fuFlags = MF_DISABLED;
	}

      /* Draw radio buttons and tickboxes. */
      else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
				wv->button_type == BUTTON_TYPE_RADIO))
	fuFlags |= MF_CHECKED;
      else
	fuFlags |= MF_UNCHECKED;
    }

  if (unicode_append_menu && out_string)
    {
      /* Convert out_string from UTF-8 to UTF-16-LE.  */
      int utf8_len = strlen (out_string);
      WCHAR * utf16_string;
      if (fuFlags & MF_OWNERDRAW)
	utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
      else
	utf16_string = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR));

      utf8to16 ((unsigned char *)out_string, utf8_len, utf16_string);
      return_value = unicode_append_menu (menu, fuFlags,
					  item != NULL ? (UINT_PTR) item
					    : (UINT_PTR) wv->call_data,
					  utf16_string);

#ifndef NTGUI_UNICODE /* Fallback does not apply when always UNICODE */
      if (!return_value)
	{
	  /* On W9x/ME, Unicode menus are not supported, though AppendMenuW
	     apparently does exist at least in some cases and appears to be
	     stubbed out to do nothing.  out_string is UTF-8, but since
	     our standard menus are in English and this is only going to
	     happen the first time a menu is used, the encoding is
	     of minor importance compared with menus not working at all.  */
	  return_value =
	    AppendMenu (menu, fuFlags,
			item != NULL ? (UINT_PTR) item: (UINT_PTR) wv->call_data,
			out_string);
	  /* Don't use Unicode menus in future, unless this is Windows
	     NT or later, where a failure of AppendMenuW does NOT mean
	     Unicode menus are unsupported.  */
	  if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT)
	    unicode_append_menu = NULL;
	}
#endif /* NTGUI_UNICODE */

      if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
	local_free (out_string);
    }
  else
    {
      return_value =
	AppendMenu (menu,
		    fuFlags,
		    item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
		    out_string );
    }

  /* This must be done after the menu item is created.  */
  if (!wv->title && wv->call_data != 0)
    {
      if (set_menu_item_info)
	{
	  MENUITEMINFO info;
	  memset (&info, 0, sizeof (info));
	  info.cbSize = sizeof (info);
	  info.fMask = MIIM_DATA;

	  /* Set help string for menu item.  Leave it as a pointer to
	     a Lisp_String until it is ready to be displayed, since GC
	     can happen while menus are active.  */
	  if (!NILP (wv->help))
	    {
	      /* We use XUNTAG below because in a 32-bit build
		 --with-wide-int we cannot pass a Lisp_Object
		 via a DWORD member of MENUITEMINFO.  */
	      /* As of Jul-2012, w32api headers say that dwItemData
		 has DWORD type, but that's a bug: it should actually
		 be ULONG_PTR, which is correct for 32-bit and 64-bit
		 Windows alike.  MSVC headers get it right; hopefully,
		 MinGW headers will, too.  */
	      eassert (STRINGP (wv->help));
	      info.dwItemData = (ULONG_PTR) XUNTAG (wv->help, Lisp_String);
	    }
	  if (wv->button_type == BUTTON_TYPE_RADIO)
	    {
	      /* CheckMenuRadioItem allows us to differentiate TOGGLE and
		 RADIO items, but is not available on NT 3.51 and earlier.  */
	      info.fMask |= MIIM_TYPE | MIIM_STATE;
	      info.fType = MFT_RADIOCHECK | MFT_STRING;
	      info.dwTypeData = out_string;
	      info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
	    }

	  set_menu_item_info (menu,
			      item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
			      FALSE, &info);
	}
    }
  SAFE_FREE ();
  return return_value;
}
コード例 #13
0
ファイル: w32notify.c プロジェクト: Ferryworld/emacs
VOID CALLBACK
watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
{
  struct notification *dirwatch;
  DWORD _bytes;
  struct notifications_set *ns = NULL;
  BOOL terminate = FALSE;

  /* Who knows what happened?  Perhaps the OVERLAPPED structure was
     freed by someone already?  In any case, we cannot do anything
     with this request, so just punt and skip it.  FIXME: should we
     raise the 'terminate' flag in this case?  */
  if (!io_info)
    {
      DebPrint(("watch_completion: io_info is null.\n"));
      return;
    }

  /* We have a pointer to our dirwatch structure conveniently stashed
     away in the hEvent member of the OVERLAPPED struct.  According to
     MSDN documentation of ReadDirectoryChangesW: "The hEvent member
     of the OVERLAPPED structure is not used by the system, so you can
     use it yourself."  */
  dirwatch = (struct notification *)io_info->hEvent;

  if (status == ERROR_OPERATION_ABORTED)
    {
      /* We've been called because the main thread told us to issue
	 CancelIo on the directory we watch, and watch_end did so.
         We must exit, without issuing another call to
         ReadDirectoryChangesW. */
      return;
    }

  /* We allocate a new set of notifications to be linked to the linked
     list of notifications set.  This will be processed by Emacs event
     loop in the main thread.  We need to duplicate the notifications
     buffer, but not the dirwatch structure.  */

  /* Implementation note: In general, allocating memory in non-main
     threads is a no-no in Emacs.  We certainly cannot call xmalloc
     and friends, because it can longjmp when allocation fails, which
     will crash Emacs because the jmp_buf is set up to a location on
     the main thread's stack.  However, we can call 'malloc' directly,
     since that is redirected to HeapAlloc that uses our private heap,
     see w32heap.c, and that is thread-safe.  */
  ns = malloc (sizeof(struct notifications_set));
  if (ns)
    {
      memset (ns, 0, sizeof(struct notifications_set));
      ns->notifications = malloc (bytes_ret);
      if (ns->notifications)
	{
	  memcpy (ns->notifications, dirwatch->buf, bytes_ret);
	  ns->size = bytes_ret;
	  ns->desc = dirwatch;
	}
      else
	{
	  free (ns);
	  ns = NULL;
	}
    }
  if (ns == NULL)
    DebPrint(("Out of memory.  Notifications lost."));

  /* Calling ReadDirectoryChangesW quickly to watch again for new
     notifications.  */
  if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
			      DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
			      dirwatch->filter, &_bytes, dirwatch->io_info,
			      watch_completion))
    {
      DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ()));
      /* If this call fails, it means that the directory is not
         watchable any more.  We need to terminate the worker thread.
         Still, we will wait until the current notifications have been
         sent to the main thread.  */
      terminate = TRUE;
    }

  if (ns)
    send_notifications(ns);

  /* If we were asked to terminate the thread, then fire the event. */
  if (terminate)
    SetEvent(dirwatch->terminate);
}
コード例 #14
0
ファイル: GameWorld.cpp プロジェクト: ehershey/development
void cGameWorld::RunCollisionTests()
{
    list< cGameEnt* >::iterator iter1, iter2;
    list< cGameEnt* >::iterator temp;
    for( iter1 = m_entList.begin();	iter1 != m_entList.end(); ++iter1 )
    {
        /**
         * test each object against all of the objects above it.
         * This is a sucky way to do things ( O(n^2) ).  A better
         * way would be to test each object only against the list
         * objects of the nearby cells.  This wouldn't be too hard
         * to do, but is left as an exercise to the reader.  Anyway,
         * since n will typically be < 10, we can waste a little time.
         */

        /**
         * Early-out if iter1 doesn't hit objects.
         */
        if( !(*iter1)->HitsObjects() )
        {
            continue;
        }

        iter2 = iter1;
        iter2++;
        for( ; iter2 != m_entList.end(); ++iter2 )
        {
            /**
             * Early-out if iter2 doesn't hit objects.
             */
            if( !(*iter2)->HitsObjects() )
            {
                continue;
            }

            /**
             * Do the objects collide?
             */
            if( bSphere3::Intersect(
                        (bSphere3&)(*iter1)->GetSphere(),
                        (bSphere3&)(*iter2)->GetSphere() ) )
            {
                // handle the collision.
                DebPrint("We had a collision!");
                temp = iter1;
                temp--;
                if( 0 == (*iter1)->RespondToCollision( (*iter2) ) )
                {
                    // if we get in here, iter1 destroyed itself as a result
                    // of the collision. (a rocket that hit a player, for
                    // example).

                    // fix iter1 and jump to the next iter1 step.
                    iter1 = temp;
                    goto iter1Died;
                }

                temp = iter2;
                temp--;
                if( 0 == (*iter2)->RespondToCollision( (*iter1) ) )
                {
                    // if we get in here, iter2 destroyed itself as a result
                    // of the collision. (a rocket that hit a player, for
                    // example).

                    // fix iter2 and continue on.
                    iter2 = temp;
                }
            }
        }

// We jump to this label when iter1 kills itself in a collision.
iter1Died:

        ; // sigh...

    }
}