Dear screen developers,

I see a bug with auto-aka feature in screen 4.0.3.  To reproduce:

0. use bash or another shell with prompt ending in '$ '.  Ensure that
   the null title command, "<esc>k<esc><backslash>", is included in
   the shell prompt.

Below, ^A means ctrl+a.  Press the following key sequence:

1. ^A:shelltitle "$ |foo"
2. ^Ac
3. ^AA bar
4. sleep 2

Expected:
1. Sets the default title for new windows to 'foo'
2. Opens a new window with title 'foo'
3. Overrides the title of the new window to 'bar'
4. Invokes a sleep command in the new window

We expect at this point the window's title to turn into 'sleep' for 2
seconds, then return back to 'bar' as requested interactively by the
user.  However, screen-4.0.3 erroneously resets the title to the
session-wide default 'foo'.

The attached patch is a proposal for a fix of this issue.  Moreover,
the arguments to the "title" command, the "-t" option, and the
"<esc>kWINDOWTITLE<esc>\" terminal sequence now undergo a similar
parsing of SEARCH|TITLE as known from "shelltitle".  This enables
interactive and programmatic changes to windows in auto-aka state,
like in

   /bin/echo -ne \\033k`pwd|sed 's/.*\///'`\\033\\\\

or in more sophisticated applications.  Use the special title "|TITLE"
to disable the auto-aka heuristic in a window.

H-C
There is a small bug with screen's auto-aka feature.  To reproduce:

0. use bash or another shell with prompt ending in '$ '.  Ensure that
   the null title command, "<esc>k<esc><backslash>", is included in
   the shell prompt.

Below, ^A means ctrl+a.  Press the following key sequence:

1. ^A:shelltitle "$ |foo"
2. ^Ac
3. ^AA bar
4. sleep 2

Expected:
1. Sets the default title for new windows to 'foo'
2. Opens a new window with title 'foo'
3. Overrides the title of the new window to 'bar'
4. Invokes a sleep command in the new window

We expect at this point the window's title to turn into 'sleep' for 2
seconds, then return back to 'bar' as requested interactively by the
user.  However, screen-4.0.3 erroneously resets the title to the
session-wide default 'foo'.

The attached patch is a proposal for a fix of this issue.  Moreover,
the special SEARCH|TITLE parsing of window names known from
"shelltitle" command is now also applied to 
- the interactive "title" command,
- the "-t" option, and
- the "<esc>kWINDOWTITLE<esc>\" terminal sequence.  (The latter can be
  used in applications like 

  /bin/echo -ne \\033k`pwd|sed 's/.*\///'`\\033\\\\ 

  to programmitically set the title of the current window.)

Use the special title "|TITLE" to disable the auto-aka heuristic in a
window.

h...@gmx.de

------------------------------------------------------------

--- screen-4.0.3.orig/ansi.c	2003-12-05 14:57:05.000000000 +0100
+++ screen-4.0.3/ansi.c	2009-07-23 16:28:38.000000000 +0200
@@ -1557,12 +1557,21 @@
       LAY_DISPLAYS(&curr->w_layer, AddStr(curr->w_string));
       break;
     case AKA:
-      if (curr->w_title == curr->w_akabuf && !*curr->w_string)
-	break;
-      ChangeAKA(curr, curr->w_string, strlen(curr->w_string));
-      if (!*curr->w_string)
-	curr->w_autoaka = curr->w_y + 1;
+      if (*curr->w_string)
+	{
+	  ChangeAKA(curr, NULL, 0); /* reset current command aka */
+	  ProcessDefaultAKA(curr, curr->w_string);
+	  ChangeAKA(curr, NULL, 0);
+	}
+      else
+	{
+	  if (curr->w_title == curr->w_akabuf) break;
+
+	  ChangeAKA(curr, NULL, 0);
+	  curr->w_autoaka = curr->w_y + 1;
+	}
       break;
+
     default:
       break;
     }
@@ -2191,10 +2200,13 @@
       p->w_akachange[i++] = c;
     }
   p->w_akachange[i] = 0;
-  p->w_title = p->w_akachange;
-  if (p->w_akachange != p->w_akabuf)
-    if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
-      p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1;
+  if (p->w_title != p->w_akabuf)
+    {
+      p->w_title = p->w_akachange;
+      if (p->w_akachange != p->w_akabuf)
+	if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
+	  p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1;
+    }
   WindowChanged(p, 't');
   WindowChanged((struct win *)0, 'w');
   WindowChanged((struct win *)0, 'W');
@@ -2208,6 +2220,8 @@
   register int len = strlen(wp->w_akabuf);
   int y;
 
+  if (!len || wp->w_title == wp->w_akabuf) return;
+
   y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
   cols = wp->w_width;
  try_line:
--- screen-4.0.3.orig/doc/screen.1	2003-12-05 14:51:57.000000000 +0100
+++ screen-4.0.3/doc/screen.1	2009-07-23 16:04:11.000000000 +0200
@@ -2885,6 +2885,15 @@
 .I screen
 prompts for one. This command was known as `aka' in previous
 releases.
+.PP
+\fIwindowtitle\fP can be in the form \*Q\fIsearch|name\fP\*U
+in which case the special heuristic for displaying the currently
+running command is enabled.  In a window under this heuristic, 
+subsequent \fIwindowtitle\fP changes only affect the \fIname\fP part
+and thus leave the heuristic enabled.  Use \fI|name\fP to disable the 
+heuristic again.
+For further details about this heuristic, see the discussion
+entitled \*QTITLES (naming windows)\*U.
 .sp
 .ne 3
 .BI "unsetenv " var
--- screen-4.0.3.orig/doc/screen.texinfo	2003-12-05 14:51:46.000000000 +0100
+++ screen-4.0.3/doc/screen.texinfo	2009-07-23 16:10:01.000000000 +0200
@@ -1943,6 +1943,14 @@
 (@kbd{C-a A})@*
 Set the name of the current window to @var{windowtitle}. If no name is 
 specified, screen prompts for one.
+
+...@var{windowtitle} can be in the form @var{search|name} in which case the
+special heuristic for displaying the currently running command is
+enabled (@pxref{Dynamic Titles}).  In a window under this heuristic,
+subsequent @var{windowtitle} changes only affect the @var{name} part and
+thus leave the heuristic enabled.  Use @var{|name} to disable the
+heuristic again.
+
 @end deffn
 
 @node Dynamic Titles, Title Prompts, Title Command, Naming Windows
@@ -1955,7 +1963,9 @@
 the @var{name} ends in a @samp{:} @code{screen} will add what it
 believes to be the current command running in the window to the end of
 the specified name (e.g. @var{name:cmd}).  Otherwise the current
-command name supersedes the shell name while it is running.
+command name supersedes the shell name while it is running.  In a window 
+under this heuristic the interactive title command (C-a A) changes only 
+the @var{name} portion.
 
 Here's how it works: you must modify your shell prompt to output a null
 title-escape-sequence (@key{ESC} k @key{ESC} \) as a part of your prompt.
--- screen-4.0.3.orig/extern.h	2003-08-22 14:27:57.000000000 +0200
+++ screen-4.0.3/extern.h	2009-07-23 15:00:27.000000000 +0200
@@ -213,6 +213,8 @@
 extern void  ApplyAttrColor __P((int, struct mchar *));
 extern void  SwitchWindow __P((int));
 extern int   StuffKey __P((int));
+extern void  ProcessDefaultAKA __P((struct win *, char *));
+
 
 /* termcap.c */
 extern int   InitTermcap __P((int, int));
--- screen-4.0.3.orig/process.c	2003-09-18 14:53:54.000000000 +0200
+++ screen-4.0.3/process.c	2009-07-29 13:20:48.000000000 +0200
@@ -33,7 +33,6 @@
 #include <sys/ioctl.h>
 #endif
 
-
 #include "config.h"
 
 /* for solaris 2.1, Unixware (SVR4.2) and possibly others: */
@@ -124,7 +123,9 @@
 static void Colonfin __P((char *, int, char *));
 static void InputSelect __P((void));
 static void InputSetenv __P((char *));
-static void InputAKA __P((void));
+static void SetDefaultAKA __P((char *));
+void ProcessDefaultAKA __P((struct win *, char *));
+static void InputDefaultAKA __P((void));
 #ifdef MULTIUSER
 static int  InputSu __P((struct win *, struct acluser **, char *));
 static void su_fin __P((char *, int, char *));
@@ -1886,9 +1887,12 @@
       break;
     case RC_TITLE:
       if (*args == 0)
-	InputAKA();
+	InputDefaultAKA();
       else
-	ChangeAKA(fore, *args, strlen(*args));
+	{
+	  SetDefaultAKA(*args);
+	  ChangeAKA(fore, NULL, 0);
+	}
       break;
     case RC_COLON:
       Input(":", 100, INP_COOKED, Colonfin, NULL);
@@ -5046,6 +5050,62 @@
   Msg(0, "%s", buf);
 }
 
+/* Here's briefly how I think the autoaka feature is implemented.  
+
+   w_akabuf is the buffer containing the raw title string.  
+   w_title points to the current title.
+   w_akachange points to the null terminating w_title.
+
+   user title string        > |bash          > |root:         bash
+
+   1) at shell prompt (triggered in ansi.c by \033k\033\\ sequence)
+
+   w_akabuf                 > \0bash\0       > \0root:\0      bash\0
+   w_title                      bash\0           root:\0      bash\0
+   w_akachange                      \0                \0      bash\0
+
+   2) when executing command (triggered in ansi.c by \n sequence)
+
+   w_akabuf                 > \0bashvi\0     > \0root:vi\0    bash\0
+   w_title                          vi\0         root:vi\0    bash\0
+   w_akachange                      vi\0              vi\0    bash\0
+                                                                               
+*/
+
+static void
+SetDefaultAKA(buf)
+     char *buf;
+{
+  ProcessDefaultAKA(fore, buf);
+}
+
+void
+ProcessDefaultAKA(f, buf)
+     struct win *f;
+     char *buf;
+{
+  char *p;
+
+  if ((p = rindex(buf, '|')) != NULL)
+    {
+      if (p == buf) buf++; /* empty lookup, switch autoaka off again */
+      strncpy(f->w_akabuf, buf, sizeof(f->w_akabuf)-1);
+      p = f->w_akabuf + (p - buf);
+      if (p >= f->w_akabuf) *p = '\0';
+      p++;
+      f->w_title = p;
+    }
+  else
+    {
+      strncpy(f->w_title, buf, 
+	      sizeof(f->w_akabuf) - (f->w_title - f->w_akabuf));
+    }
+  f->w_akabuf[sizeof(f->w_akabuf)-1] = '\0';
+  f->w_akachange = f->w_title + strlen(f->w_title);
+
+  f->w_autoaka = f->w_y + 1;
+}
+
 static void
 AKAfin(buf, len, data)
 char *buf;
@@ -5053,12 +5113,14 @@
 char *data;	/* dummy */
 {
   ASSERT(display);
-  if (len && fore)
-    ChangeAKA(fore, buf, strlen(buf));
+  if (len && fore) {
+    SetDefaultAKA(buf);
+    ChangeAKA(fore, NULL, 0);
+  }
 }
 
 static void
-InputAKA()
+InputDefaultAKA()
 {
   char *s, *ss;
   int n;

Reply via email to