Function: format-mode-line

format-mode-line is a function defined in xdisp.c.

Signature

(format-mode-line FORMAT &optional FACE WINDOW BUFFER)

Documentation

Return a string formatted according to mode-line format specification.

First arg FORMAT specifies the mode line format (see mode-line-format for details) to use.

By default, the format is evaluated for the currently selected window.

Optional second arg FACE specifies the face property to put on all characters for which no face is specified. The value nil means the default face. The value t means whatever face the window's mode line currently uses (either mode-line or mode-line-inactive, depending on whether the window is the selected window or not). An integer value means the value string has no text properties.

Optional third and fourth args WINDOW and BUFFER specify the window and buffer to use as the context for the formatting (defaults are the selected window and the WINDOW's buffer).

View in manual

Probably introduced at or before Emacs version 22.1.

Source Code

// Defined in /usr/src/emacs/src/xdisp.c
{
  struct it it;
  int len;
  struct window *w;
  struct buffer *old_buffer = NULL;
  int face_id;
  bool no_props = FIXNUMP (face);
  specpdl_ref count = SPECPDL_INDEX ();
  Lisp_Object str;
  int string_start = 0;

  w = decode_any_window (window);
  XSETWINDOW (window, w);

  if (NILP (buffer))
    buffer = w->contents;
  CHECK_BUFFER (buffer);
  if (!BUFFER_LIVE_P (XBUFFER (buffer)))
    error ("Attempt to format a mode line for a dead buffer");

  /* Make formatting the modeline a non-op when noninteractive, otherwise
     there will be problems later caused by a partially initialized frame.  */
  if (NILP (format) || noninteractive)
    return empty_unibyte_string;

  if (no_props)
    face = Qnil;

  face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
    : EQ (face, Qt) ? (EQ (window, selected_window)
		       ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
    : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
    : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
    : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
    : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
    : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
    : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
    : DEFAULT_FACE_ID;

  old_buffer = current_buffer;

  /* Save things including mode_line_proptrans_alist,
     and set that to nil so that we don't alter the outer value.  */
  record_unwind_protect (unwind_format_mode_line,
			 format_mode_line_unwind_data
			   (XFRAME (WINDOW_FRAME (w)),
			    old_buffer, selected_window, true));
  mode_line_proptrans_alist = Qnil;

  Fselect_window (window, Qt);
  set_buffer_internal_1 (XBUFFER (buffer));

  init_iterator (&it, w, -1, -1, NULL, face_id);

  /* Make sure `base_line_number` is fresh in case we encounter a `%l`.  */
  if (current_buffer == XBUFFER ((w)->contents)
      && !BASE_LINE_NUMBER_VALID_P (w))
    w->base_line_number = 0;

  if (no_props)
    {
      mode_line_target = MODE_LINE_NOPROP;
      mode_line_string_face_prop = Qnil;
      mode_line_string_list = Qnil;
      string_start = MODE_LINE_NOPROP_LEN (0);
    }
  else
    {
      mode_line_target = MODE_LINE_STRING;
      mode_line_string_list = Qnil;
      mode_line_string_face = face;
      mode_line_string_face_prop
	= NILP (face) ? Qnil : list2 (Qface, face);
    }

  push_kboard (FRAME_KBOARD (it.f));
  display_mode_element (&it, 0, 0, 0, format, Qnil, false);
  pop_kboard ();

  if (no_props)
    {
      len = MODE_LINE_NOPROP_LEN (string_start);
      str = make_string (mode_line_noprop_buf + string_start, len);
    }
  else
    {
      mode_line_string_list = Fnreverse (mode_line_string_list);
      str = Fmapconcat (Qidentity, mode_line_string_list,
			empty_unibyte_string);
    }

  return unbind_to (count, str);
}