]> granicus.if.org Git - neomutt/commitdiff
Terminal status line support, based on the xterm title patch.
authorDavid Champion <dgc@uchicago.edu>
Tue, 22 Oct 2013 19:15:01 +0000 (14:15 -0500)
committerDavid Champion <dgc@uchicago.edu>
Tue, 22 Oct 2013 19:15:01 +0000 (14:15 -0500)
Christoph Berg took the xterm title patch from the mutt mailing list and
maintained it for Debian:
* Changes made:
  - 2007-01-27 myon: using %P caused a segfault, updated status.c to catch
    menu==NULL.
  - 2007-02-20 myon: make the note about the xterm_set_titles defaults a
    comment.
  - 2008-08-02 myon: move set_xterm_* prototypes into the proper header file
    (cleaner code, no functional change, evades conflict with sidebar patch)

This update reworks the Debian version as generic support for tsl/fsl
terminfo capability.  It no longer depends on a static list of supported
terminal types, although it will use default support for these terminal
types *if* they do not advertise tsl/fsl or XT in terminfo.

The generic terminal status line can be implemented in any fashion, and
on hardware terminals it can be a special out-of-screen region of the
display.  Most modern terminal emulators appear to emulate the status
line in the window title; thus the notion of the tsl escape as an xterm
window title escape.

Configuration variables have been renamed:
$ts_status_format
    format string (using $status_format codes) for the terminal status line
$ts_icon_format
    format string (using $status_format codes) for the xterm icon name
$ts_enabled
    toggle for whether to issue status updates

The old configuration names exist as synonyms.

Logic flow:
* If tsl (string) is set in terminfo, mutt will use that escape to switch
  to the status area, and will use fsl to switch back to the regular
  display area.
* Otherwise, if XT (boolean) is set in terminfo, mutt will use the
  standard xterm-compatible escapes.
* Otherwise, if $TERM matches a known terminal type, mutt will use the
  standard xterm-compatible escapes.
* Otherwise, this feature is disabled.

= NOTE =

The XTerm icon escape sequence is not formalized in terminfo, so the
egregious kludge of hardcoding the escape is necessary in this case.
However, some terminal emulators (e.g. MacOS X Terminal.app) will set
the status line (window title) when the icon sequence is received.
Since there is no way to detect this behavior, the only solution is to
write your configuration to take it into account.  Rather than add a
variable to control icon escapes separately, we just provide the advice:
if you use such a terminal, you may wish to set ts_icon_format to an
empty string.  This will cause it not to be used.

configure.ac
curs_main.c
globals.h
init.h
main.c
mutt.h
mutt_menu.h
pager.c
protos.h
status.c

index 1b6e01072ea5426ef4760e350d8846c801215d96..20c59e069645ff5b8bfd94a9b1e9af90e849fda9 100644 (file)
@@ -295,6 +295,7 @@ main ()
         if test "$ac_cv_func_decl_resizeterm" = yes; then
                 MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS resize.o"
         fi
+        AC_CHECK_FUNCS([use_extended_names])
         LIBS="$old_LIBS"
         ])
 
index aa4b044d6520ccc3066540af5ad88f5341be054c..8553102457bc96794c8f13cd2d580f9be0c692c4 100644 (file)
@@ -110,6 +110,83 @@ static const char *No_visible = N_("No visible messages.");
 
 extern size_t UngetCount;
 
+/* de facto standard escapes for tsl/fsl */
+static char *tsl = "\033]0;";
+static char *fsl = "\007";
+
+/* terminal status capability check. terminfo must have been initialized. */
+short mutt_ts_capability(void)
+{
+  char *term = getenv("TERM");
+  char *tcaps;
+  int tcapi;
+  char **termp;
+  char *known[] = {
+    "color-xterm",
+    "cygwin",
+    "eterm",
+    "kterm",
+    "nxterm",
+    "putty",
+    "rxvt",
+    "screen",
+    "xterm",
+    NULL
+  };
+
+  /* If tsl is set, then terminfo says that status lines work. */
+  tcaps = tigetstr("tsl");
+  if (tcaps && tcaps != (char *)-1 && *tcaps)
+  {
+    /* update the static defns of tsl/fsl from terminfo */
+    tsl = safe_strdup(tcaps);
+
+    tcaps = tigetstr("fsl");
+    if (tcaps && tcaps != (char *)-1 && *tcaps)
+      fsl = safe_strdup(tcaps);
+
+    return 1;
+  }
+
+  /* If XT (boolean) is set, then this terminal supports the standard escape. */
+  /* Beware: tigetflag returns -1 if XT is invalid or not a boolean. */
+#ifdef HAVE_USE_EXTENDED_NAMES
+  use_extended_names (TRUE);
+  tcapi = tigetflag("XT");
+  if (tcapi == 1)
+    return 1;
+#endif /* HAVE_USE_EXTENDED_NAMES */
+
+  /* Check term types that are known to support the standard escape without
+   * necessarily asserting it in terminfo. */
+  for (termp = known; termp; termp++)
+  {
+    if (term && *termp && mutt_strncasecmp (term, *termp, strlen(*termp)))
+      return 1;
+  }
+
+  /* not supported */
+  return 0;
+}
+
+void mutt_ts_status(char *str)
+{
+  /* If empty, do not set.  To clear, use a single space. */
+  if (str == NULL || *str == '\0')
+    return;
+  fprintf(stderr, "%s%s%s", tsl, str, fsl);
+}
+
+void mutt_ts_icon(char *str)
+{
+  /* If empty, do not set.  To clear, use a single space. */
+  if (str == NULL || *str == '\0')
+    return;
+
+  /* icon setting is not supported in terminfo, so hardcode the escape - yuck */
+  fprintf(stderr, "\033]1;%s\007", str);
+}
+
 void index_make_entry (char *s, size_t l, MUTTMENU *menu, int num)
 {
   format_flag flag = M_FORMAT_MAKEPRINT | M_FORMAT_ARROWCURSOR | M_FORMAT_INDEX;
@@ -560,6 +637,13 @@ int mutt_index_menu (void)
        mutt_paddstr (COLS, buf);
        NORMAL_COLOR;
        menu->redraw &= ~REDRAW_STATUS;
+       if (option(OPTTSENABLED) && TSSupported)
+       {
+         menu_status_line (buf, sizeof (buf), menu, NONULL (TSStatusFormat));
+         mutt_ts_status(buf);
+         menu_status_line (buf, sizeof (buf), menu, NONULL (TSIconFormat));
+         mutt_ts_icon(buf);
+       }
       }
 
       menu->redraw = 0;
index 6fefe5b030e86bd797e07872626a1f32eee612c7..6c21fedfd70a67ccdf5b944c3419725dc820a42e 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -139,6 +139,9 @@ WHERE char *StChars;
 WHERE char *Status;
 WHERE char *Tempdir;
 WHERE char *Tochars;
+WHERE char *TSStatusFormat;
+WHERE char *TSIconFormat;
+WHERE short TSSupported;
 WHERE char *Username;
 WHERE char *Visual;
 
diff --git a/init.h b/init.h
index b5b288693fcf1dd9e0a384af57dfaff282f807f3..d0c3d45944385097b085e44526f173e98c731498 100644 (file)
--- a/init.h
+++ b/init.h
@@ -3241,6 +3241,27 @@ struct option_t MuttVars[] = {
   ** by \fIyou\fP.  The sixth character is used to indicate when a mail
   ** was sent to a mailing-list you subscribe to.
   */
+  {"ts_icon_format",   DT_STR,  R_BOTH, UL &TSIconFormat, UL "M%?n?AIL&ail?"},
+  /*
+  ** .pp
+  ** Controls the format of the icon title, as long as ``$$ts_enabled'' is set.
+  ** This string is identical in formatting to the one used by
+  ** ``$$status_format''.
+  */
+  {"ts_enabled",       DT_BOOL,  R_BOTH, OPTTSENABLED, 0},
+  /* The default must be off to force in the validity checking. */
+  /*
+  ** .pp
+  ** Controls whether mutt tries to set the terminal status line and icon name.
+  ** Most terminal emulators emulate the status line in the window title.
+  */
+  {"ts_status_format", DT_STR,   R_BOTH, UL &TSStatusFormat, UL "Mutt with %?m?%m messages&no messages?%?n? [%n NEW]?"},
+  /*
+  ** .pp
+  ** Controls the format of the terminal status line (or window title),
+  ** provided that ``$$ts_enabled'' has been set. This string is identical in
+  ** formatting to the one used by ``$$status_format''.
+  */
 #ifdef USE_SOCKET
   { "tunnel",            DT_STR, R_NONE, UL &Tunnel, UL 0 },
   /*
@@ -3412,6 +3433,15 @@ struct option_t MuttVars[] = {
   ** Also see the $$read_inc, $$net_inc and $$time_inc variables and the
   ** ``$tuning'' section of the manual for performance considerations.
   */
+  {"xterm_icon",       DT_SYN,  R_NONE, UL "ts_icon_format", 0 },
+  /*
+  */
+  {"xterm_title",      DT_SYN,  R_NONE, UL "ts_status_format", 0 },
+  /*
+  */
+  {"xterm_set_titles", DT_SYN,  R_NONE, UL "ts_enabled", 0 },
+  /*
+  */
   /*--*/
   { NULL, 0, 0, 0, 0 }
 };
diff --git a/main.c b/main.c
index 0ce245b5d750fa6016f5ce4bc5bfa2ab89617a98..204a5ca63df71ea8b1d3c4c923796e284bed7eea 100644 (file)
--- a/main.c
+++ b/main.c
@@ -768,6 +768,9 @@ int main (int argc, char **argv)
   if (!option (OPTNOCURSES))
     start_curses ();
 
+  /* check whether terminal status is supported (must follow curses init) */
+  TSSupported = mutt_ts_capability();
+
   /* set defaults and read init files */
   mutt_init (flags & M_NOSYSRC, commands);
   mutt_free_list (&commands);
diff --git a/mutt.h b/mutt.h
index 06e3c8cd696a89efe93219e441983fc2ec6e605f..2c4ed87d65ec0f8871a53ef661a9764f6ce5e2ff 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -431,6 +431,7 @@ enum
   OPTTHOROUGHSRC,
   OPTTHREADRECEIVED,
   OPTTILDE,
+  OPTTSENABLED,
   OPTUNCOLLAPSEJUMP,
   OPTUSE8BITMIME,
   OPTUSEDOMAIN,
index d459bef582ade8c743beffc4f60a30ee0eccda5f..8192019e2cc8254c03f9f9227e7452c7a2ec4182 100644 (file)
@@ -103,6 +103,9 @@ void menu_current_middle (MUTTMENU *);
 void menu_current_bottom (MUTTMENU *);
 void menu_check_recenter (MUTTMENU *);
 void menu_status_line (char *, size_t, MUTTMENU *, const char *);
+short mutt_ts_capability (void);
+void mutt_ts_status (char *);
+void mutt_ts_icon (char *);
 
 MUTTMENU *mutt_new_menu (int);
 void mutt_menuDestroy (MUTTMENU **);
diff --git a/pager.c b/pager.c
index 486d8c8d6cbcb6fc21f99b93267f230c2ebd8e11..4f7e7beeb86efbbd90af38862d089310910c8538 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -1812,6 +1812,13 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
        mutt_paddstr (COLS, bn);
       }
       NORMAL_COLOR;
+      if (option(OPTTSENABLED) && TSSupported)
+      {
+       menu_status_line (buffer, sizeof (buffer), index, NONULL (TSStatusFormat));
+       mutt_ts_status(buffer);
+       menu_status_line (buffer, sizeof (buffer), index, NONULL (TSIconFormat));
+       mutt_ts_icon(buffer);
+      }
     }
 
     if ((redraw & REDRAW_INDEX) && index)
index 8542f91eeb1ff23a4b273182add4d412d22c7566..f17852dc5b4321c2c2e2875e044af6239ec4e91a 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -250,6 +250,7 @@ void mutt_signal_init (void);
 void mutt_stamp_attachment (BODY *a);
 void mutt_tabs_to_spaces (char *);
 void mutt_tag_set_flag (int, int);
+short mutt_ts_capability (void);
 void mutt_unblock_signals (void);
 void mutt_unblock_signals_system (int);
 void mutt_update_encoding (BODY *a);
index 1bb9a5a45b6713b4f1aa372f4093e45e98ed1950..6051e3af6b9bb18fc140fc49c63fca2d6dc89110 100644 (file)
--- a/status.c
+++ b/status.c
@@ -195,6 +195,8 @@ status_format_str (char *buf, size_t buflen, size_t col, char op, const char *sr
       break;
 
     case 'P':
+      if (!menu)
+       break;
       if (menu->top + menu->pagelen >= menu->max)
        cp = menu->top ? "end" : "all";
       else