Function: frame-or-buffer-changed-p

frame-or-buffer-changed-p is a function defined in dispnew.c.

Signature

(frame-or-buffer-changed-p &optional VARIABLE)

Documentation

Return non-nil if the frame and buffer state appears to have changed.

VARIABLE is a variable name whose value is either nil or a state vector that will be updated to contain all frames and buffers, aside from buffers whose names start with space, along with the buffers' read-only and modified flags. This allows a fast check to see whether buffer menus might need to be recomputed. If this function returns non-nil, it updates the internal vector to reflect the current state.

If VARIABLE is nil, an internal variable is used. Users should not pass nil for VARIABLE.

Probably introduced at or before Emacs version 22.1.

Source Code

// Defined in /usr/src/emacs/src/dispnew.c
{
  Lisp_Object state, tail, frame, buf;
  ptrdiff_t n, idx;

  if (! NILP (variable))
    {
      CHECK_SYMBOL (variable);
      state = Fsymbol_value (variable);
      if (! VECTORP (state))
	goto changed;
    }
  else
    state = frame_and_buffer_state;

  idx = 0;
  FOR_EACH_FRAME (tail, frame)
    {
      if (idx == ASIZE (state))
	goto changed;
      if (!BASE_EQ (AREF (state, idx++), frame))
	goto changed;
      if (idx == ASIZE (state))
	goto changed;
      if (!EQ (AREF (state, idx++), XFRAME (frame)->name))
	goto changed;
    }
  /* Check that the buffer info matches.  */
  FOR_EACH_LIVE_BUFFER (tail, buf)
    {
      /* Ignore buffers that aren't included in buffer lists.  */
      if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
	continue;
      if (idx == ASIZE (state))
	goto changed;
      if (!BASE_EQ (AREF (state, idx++), buf))
	goto changed;
      if (idx == ASIZE (state))
	goto changed;
      if (!EQ (AREF (state, idx++), BVAR (XBUFFER (buf), read_only)))
	goto changed;
      if (idx == ASIZE (state))
	goto changed;
      if (!EQ (AREF (state, idx++), Fbuffer_modified_p (buf)))
	goto changed;
    }
  if (idx == ASIZE (state))
    goto changed;
  /* Detect deletion of a buffer at the end of the list.  */
  if (EQ (AREF (state, idx), Qlambda))
    return Qnil;

  /* Come here if we decide the data has changed.  */
 changed:
  /* Count the size we will need.
     Start with 1 so there is room for at least one lambda at the end.  */
  n = 1;
  FOR_EACH_FRAME (tail, frame)
    n += 2;
  FOR_EACH_LIVE_BUFFER (tail, buf)
    n += 3;
  /* Reallocate the vector if data has grown to need it,
     or if it has shrunk a lot.  */
  if (! VECTORP (state)
      || n > ASIZE (state)
      || n + 20 < ASIZE (state) / 2)
    /* Add 20 extra so we grow it less often.  */
    {
      state = make_vector (n + 20, Qlambda);
      if (! NILP (variable))
	Fset (variable, state);
      else
	frame_and_buffer_state = state;
    }

  /* Record the new data in the (possibly reallocated) vector.  */
  idx = 0;
  FOR_EACH_FRAME (tail, frame)
    {
      ASET (state, idx, frame);
      idx++;
      ASET (state, idx, XFRAME (frame)->name);
      idx++;
    }
  FOR_EACH_LIVE_BUFFER (tail, buf)
    {
      /* Ignore buffers that aren't included in buffer lists.  */
      if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
	continue;
      ASET (state, idx, buf);
      idx++;
      ASET (state, idx, BVAR (XBUFFER (buf), read_only));
      idx++;
      ASET (state, idx, Fbuffer_modified_p (buf));
      idx++;
    }
  /* Fill up the vector with lambdas (always at least one).  */
  ASET (state, idx, Qlambda);
  idx++;
  while (idx < ASIZE (state))
    {
      ASET (state, idx, Qlambda);
      idx++;
    }
  /* Make sure we didn't overflow the vector.  */
  eassert (idx <= ASIZE (state));
  return Qt;
}