Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Terminal I/O handling fix



This is an updated form of a patch I posted some time ago which was
just too late to make it into zsh 2.4 (and which had some problems
with select() which I later fixed).  It separates the I/O of zle from
direct reliance on stdin/stdout or FD's 0 and 1.

There are are now two good reasons for this; the second I didn't know
about when I first posted this, but it should now be familiar.

1) Grown-up shells keep terminal editing separate from standard input
and output.  For example, you should be able to do

% exec >logfile
% echo foo
% exec >$TTY
% cat logfile
foo
% 

without any effect on editing.  This works in sh, bash, and ksh.  At
the moment, all the editing output in zsh goes to stdout as well.  

The difficult case is `exec < file' since that's supposed to change
where commands are being read from.  In fact, if zle was being used,
it always attempted to use zle to read from the file.  I've put an
explicit test in execcmd() for this, so that if commands are
notionally coming from stdin in an interactive shell and you do 'exec
< file' it tries to work out what to do.  The case where `file' is
actually a terminal is the hardest, since then there's in principle a
lot more work to do.  In fact, all I've done is re-open the terminal
files (so that exec <$TTY to fix up your terminal works like it always
did, in fact now it always makes editing work sensibly which it didn't
before when stdout was also used).  Ideally this probably needs to be
more sophisticated, or combined with the code in setmoreflags() which
sets up terminal handling initially.  (At the moment that does other
things, which is why I didn't use it.)

2) It won't have escaped your notice that redirecting the input of a
shell function has a dire effect on interactive shells at the moment
(I reported this a few weeks ago and it's now top of Zoltan's BUGS
file).  This patch helps since the terminal FD and file now aren't
affected by redirection (except for the exec < business I just talked
about).

% fn() { : }
% true | true
% fn < /dev/null
%		# kein Problem.

There is a remaining problem here, in that FD 0 does not recover ---
this is the same problem that was there before, it just doesn't affect
zle any more.  `exec <$TTY' fixes it, but it still probably needs some
work.  At least the shell doesn't exit any more.

The big downside is that we now need to remember to use `shout' for
all output in zle_*.c (with the exceptions noted in the comment at the
top of zle_main.c), and people are liable to forget.  There's probably
enough use of it there already to jog memories.

I'd have liked to make this patch smaller, but the central problem is
that zle is not well separated from the other parts of zsh.  That's
what's necessitated the extra couple of chunks of code.  It's quite
possible there are some remaining anomalies between stdout/shout.

*** Src/exec.c.tty	Tue May 23 15:07:40 1995
--- Src/exec.c	Tue May 23 15:36:01 1995
***************
*** 1271,1276 ****
--- 1271,1293 ----
  		    execerr();
  		}
  		addfd(forked, save, mfds, fn->fd1, fil, 0);
+ 		/* If this is 'exec < file', read from stdin, not terminal
+ 		 * --- unless `file' is a terminal.  (PWS 1995/05/23)
+ 		 */
+ 		if (nullexec && fn->fd1 == 0 && isset(SHINSTDIN) && interact)
+ 		    if (isatty(0)) {
+ 			if (shout) {
+ 			    fclose(shout);
+ 			    shout = 0;
+ 			}
+ 			SHTTY = movefd(open(ttyname(0), O_RDWR));
+ 			if (SHTTY == -1)
+ 			    opts[MONITOR] = OPT_UNSET;
+ 			else
+ 			    shout = fdopen(SHTTY, "w");
+ 			opts[USEZLE] = shout ? OPT_UNSET : OPT_SET;
+ 		    } else
+ 			opts[USEZLE] = OPT_UNSET;
  	    } else if (fn->type == CLOSE) {
  		if (!forked && fn->fd1 < 10)
  		    save[fn->fd1] = movefd(fn->fd1);
*** Src/globals.h.tty	Fri May 19 10:10:11 1995
--- Src/globals.h	Tue May 23 14:20:30 1995
***************
*** 387,393 ****
  /* the shell tty fd */
   
  EXTERN int SHTTY;
!  
  /* the stack of aliases we are expanding */
   
  EXTERN struct alias *alstack[MAXAL];
--- 387,397 ----
  /* the shell tty fd */
   
  EXTERN int SHTTY;
! 
! /* the FILE attached to the shell tty */
! 
! EXTERN FILE *shout;
! 
  /* the stack of aliases we are expanding */
   
  EXTERN struct alias *alstack[MAXAL];
*** Src/init.c.tty	Fri May 19 10:10:35 1995
--- Src/init.c	Tue May 23 15:45:03 1995
***************
*** 160,166 ****
      opts[HASHLISTALL] = OPT_SET;
      opts[HASHDIRS]    = OPT_SET;
      opts[INTERACTIVE] = (isatty(0)) ? OPT_SET : OPT_UNSET;
!     opts[USEZLE]      = (interact && SHTTY != -1) ? OPT_SET : OPT_UNSET;
  
      if (getuid() != geteuid() || getgid() != getegid())
  	opts[PRIVILEGED] = OPT_SET;
--- 160,166 ----
      opts[HASHLISTALL] = OPT_SET;
      opts[HASHDIRS]    = OPT_SET;
      opts[INTERACTIVE] = (isatty(0)) ? OPT_SET : OPT_UNSET;
!     /* USEZLE is now set in setmoreflags() after attempt to open terminal */
  
      if (getuid() != geteuid() || getgid() != getegid())
  	opts[PRIVILEGED] = OPT_SET;
***************
*** 322,328 ****
      subsh = 0;
  
  #ifdef JOB_CONTROL
! 	SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty", O_RDWR));
  	if (SHTTY == -1)
  	    opts[MONITOR] = OPT_UNSET;
  	else {
--- 322,329 ----
      subsh = 0;
  
  #ifdef JOB_CONTROL
! 	/* Make sure the tty is opened read/write. */
! 	SHTTY = movefd(open(isatty(0) ? ttyname(0) : "/dev/tty", O_RDWR));
  	if (SHTTY == -1)
  	    opts[MONITOR] = OPT_UNSET;
  	else {
***************
*** 331,336 ****
--- 332,339 ----
  
          ioctl(SHTTY, TIOCSETD, (char *)&ldisc);
  # endif
+ 	/* Associate terminal file descriptor with a FILE */
+ 	shout = fdopen(SHTTY, "w");
          gettyinfo(&shttyinfo);	/* get tty state */
  # if defined(__sgi)
          if (shttyinfo.tio.c_cc[VSWTCH] <= 0)	/* hack for irises */
***************
*** 357,366 ****
      }
  #else   /* no JOB_CONTROL */
      opts[MONITOR] = OPT_UNSET;
!     SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty", O_RDWR));
      if (SHTTY != -1)
  	gettyinfo(&shttyinfo);
  #endif
  }
  
  /**/
--- 360,372 ----
      }
  #else   /* no JOB_CONTROL */
      opts[MONITOR] = OPT_UNSET;
!     SHTTY = movefd(open(isatty(0) ? ttyname(0) : "/dev/tty", O_RDWR));
!     shout = fdopen(SHTTY, "w");
      if (SHTTY != -1)
  	gettyinfo(&shttyinfo);
  #endif
+ 
+     opts[USEZLE] = (interact && shout) ? OPT_SET : OPT_UNSET;
  }
  
  /**/
*** Src/utils.c.tty	Fri May 19 10:10:55 1995
--- Src/utils.c	Tue May 23 14:20:31 1995
***************
*** 1063,1073 ****
  {
      fflush(stdin);
      if (*s == '/')
! 	fprintf(stderr, "zsh: sure you want to delete all the files in %s? ", s);
      else
! 	fprintf(stderr, "zsh: sure you want to delete all the files in %s/%s? ",
  		(pwd[1]) ? pwd : "", s);
!     fflush(stderr);
      feep();
      return (getquery() == 'y');
  }
--- 1063,1074 ----
  {
      fflush(stdin);
      if (*s == '/')
! 	fprintf(shout, "zsh: sure you want to delete all the files in %s? ",
! 		s);
      else
! 	fprintf(shout, "zsh: sure you want to delete all the files in %s/%s? ",
  		(pwd[1]) ? pwd : "", s);
!     fflush(shout);
      feep();
      return (getquery() == 'y');
  }
***************
*** 1092,1098 ****
      if (val) {
  	if (!isem)
  	    settyinfo(&shttyinfo);
! 	write(2, "n\n", 2);
  	return 'n';
      }
  #endif
--- 1093,1099 ----
      if (val) {
  	if (!isem)
  	    settyinfo(&shttyinfo);
! 	write(SHTTY, "n\n", 2);
  	return 'n';
      }
  #endif
*** Src/zle_main.c.tty	Fri May 19 10:11:03 1995
--- Src/zle_main.c	Tue May 23 14:48:11 1995
***************
*** 29,34 ****
--- 29,49 ----
   *
   */
  
+ /*
+  * Note on output from zle (PWS 1995/05/23):
+  *
+  * All input and output from the editor should be to/from the file descriptor
+  * `SHTTY' and FILE `shout'.  (Normally, the former is used for input
+  * operations, reading one key at a time, and the latter for output
+  * operations, flushing after each refresh()).  Thus fprintf(shout, ...),
+  * putc(..., shout), etc., should be used for output within zle.
+  *
+  * However, the functions printbind() and printbinding() can be invoked from
+  * the builtin bindkey as well as zle, in which case output should be to
+  * stdout.  For this purpose, the static variable FILE *bindout exists, which
+  * is set to stdout in bin_bindkey() and shout in zleread().
+  */
+ 
  #define ZLEGLOBALS
  #define ZLE
  #include "zsh.h"
***************
*** 241,248 ****
  		expire_tv.tv_sec = exp100ths / 100;
  		expire_tv.tv_usec = (exp100ths % 100) * 10000L;
  		FD_ZERO(&foofd);
! 		FD_SET(0, &foofd);
! 		if (select(1, (SELECT_ARG_2_T) & foofd, NULL, NULL, &expire_tv) <= 0)
  		    return EOF;
  	    }
  #else
--- 256,264 ----
  		expire_tv.tv_sec = exp100ths / 100;
  		expire_tv.tv_usec = (exp100ths % 100) * 10000L;
  		FD_ZERO(&foofd);
! 		FD_SET(SHTTY, &foofd);
! 		if (select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
! 			   NULL, NULL, &expire_tv) <= 0)
  		    return EOF;
  	    }
  #else
***************
*** 256,262 ****
  #  else
  	    ioctl(SHTTY, TCSETA, &ti.tio);
  #  endif
! 	    r = read(0, &cc, 1);
  #  ifdef HAVE_TERMIOS_H
  	    tcsetattr(SHTTY, TCSANOW, &ti.tio);
  #  else
--- 272,278 ----
  #  else
  	    ioctl(SHTTY, TCSETA, &ti.tio);
  #  endif
! 	    r = read(SHTTY, &cc, 1);
  #  ifdef HAVE_TERMIOS_H
  	    tcsetattr(SHTTY, TCSANOW, &ti.tio);
  #  else
***************
*** 266,272 ****
  # endif
  #endif
  	}
! 	while ((r = read(0, &cc, 1)) != 1) {
  	    if (r == 0) {
  		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
  		   that were typed while commands are running.  Unfortuantely
--- 282,288 ----
  # endif
  #endif
  	}
! 	while ((r = read(SHTTY, &cc, 1)) != 1) {
  	    if (r == 0) {
  		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
  		   that were typed while commands are running.  Unfortuantely
***************
*** 322,327 ****
--- 338,346 ----
      return ret;
  }
  
+ /* Where to print out bindings:  either stdout, or the zle output shout */
+ static FILE *bindout;
+ 
  /* read a line */
  
  /**/
***************
*** 340,346 ****
      tv.tv_sec = 0;
  #endif
  
!     fflush(stdout);
      fflush(stderr);
      intr();
      insmode = unset(OVERSTRIKE);
--- 359,365 ----
      tv.tv_sec = 0;
  #endif
  
!     fflush(shout);
      fflush(stderr);
      intr();
      insmode = unset(OVERSTRIKE);
***************
*** 365,370 ****
--- 384,390 ----
      addedsuffix = complexpect = vichgflag = 0;
      viinsbegin = 0;
      statusline = NULL;
+     bindout = shout;		/* always print bindings on terminal */
      if ((s = (unsigned char *)getnode(bufstack))) {
  	setline((char *)s);
  	zsfree((char *)s);
***************
*** 381,387 ****
      }
      initundo();
      if (unset(NOPROMPTCR))
! 	putchar('\r');
      if (tmout)
  	alarm(tmout);
      zleactive = 1;
--- 401,407 ----
      }
      initundo();
      if (unset(NOPROMPTCR))
! 	putc('\r', shout);
      if (tmout)
  	alarm(tmout);
      zleactive = 1;
***************
*** 438,447 ****
  	}
  #ifdef HAVE_SELECT
  	if (baud && !(lastcmd & ZLE_MENUCMP)) {
! 	    FD_SET(0, &foofd);
  	    if ((tv.tv_usec = cost * costmult) > 500000)
  		tv.tv_usec = 500000;
! 	    if (!kungetct && select(1, (SELECT_ARG_2_T) & foofd, NULL, NULL, &tv) <= 0)
  		refresh();
  	} else
  #endif
--- 458,468 ----
  	}
  #ifdef HAVE_SELECT
  	if (baud && !(lastcmd & ZLE_MENUCMP)) {
! 	    FD_SET(SHTTY, &foofd);
  	    if ((tv.tv_usec = cost * costmult) > 500000)
  		tv.tv_usec = 500000;
! 	    if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
! 				    NULL, NULL, &tv) <= 0)
  		refresh();
  	} else
  #endif
***************
*** 781,801 ****
      while (len--) {
  	ch = (unsigned char)*s++;
  	if (ch & 0x80) {
! 	    printf("\\M-");
  	    ch &= 0x7f;
  	}
  	if (icntrl(ch))
  	    switch (ch) {
  	    case 0x7f:
! 		printf("^?");
  		break;
  	    default:
! 		printf("^%c", (ch | 0x40));
  		break;
  	} else {
  	    if (ch == '\\' || ch == '^')
! 		putchar('\\');
! 	    putchar(ch);
  	}
      }
  }
--- 802,822 ----
      while (len--) {
  	ch = (unsigned char)*s++;
  	if (ch & 0x80) {
! 	    fprintf(bindout, "\\M-");
  	    ch &= 0x7f;
  	}
  	if (icntrl(ch))
  	    switch (ch) {
  	    case 0x7f:
! 		fprintf(bindout, "^?");
  		break;
  	    default:
! 		fprintf(bindout, "^%c", (ch | 0x40));
  		break;
  	} else {
  	    if (ch == '\\' || ch == '^')
! 		putc('\\', bindout);
! 	    putc(ch, bindout);
  	}
      }
  }
***************
*** 808,822 ****
  
      if (k->func == z_undefinedkey)
  	return;
!     putchar('\"');
      printbind(str, (len = strlen(str)) ? len : 1);
!     printf("\"\t");
      if (k->func == z_sendstring) {
! 	putchar('\"');
  	printbind(k->str, k->len);
! 	printf("\"\n");
      } else
! 	printf("%s\n", zlecmds[k->func].name);
  }
  
  /**/
--- 829,843 ----
  
      if (k->func == z_undefinedkey)
  	return;
!     putc('\"', bindout);
      printbind(str, (len = strlen(str)) ? len : 1);
!     fprintf(bindout, "\"\t");
      if (k->func == z_sendstring) {
! 	putc('\"', bindout);
  	printbind(k->str, k->len);
! 	fprintf(bindout, "\"\n");
      } else
! 	fprintf(bindout, "%s\n", zlecmds[k->func].name);
  }
  
  /**/
***************
*** 853,858 ****
--- 874,880 ----
  	return 0;
      }
      tab = (ops['a']) ? altbindtab : mainbindtab;
+     bindout = stdout;	/* print bindings to stdout */
      if (!*argv) {
  	char buf[2];
  
***************
*** 1038,1044 ****
      }
      else
  	printbind(cky->nam, (len = strlen(cky->nam)) ? len : 1);
!     printf(" is ");
      if (cmd == z_sendstring) {
  	if (!cky) {
  	    char buf[2];
--- 1060,1066 ----
      }
      else
  	printbind(cky->nam, (len = strlen(cky->nam)) ? len : 1);
!     fprintf(shout, " is ");
      if (cmd == z_sendstring) {
  	if (!cky) {
  	    char buf[2];
***************
*** 1047,1062 ****
  	    buf[1] = '\0';
  	    cky = (Key) gethnode(buf, xbindtab);
  	}
! 	putchar('"');
  	printbind(cky->str, cky->len);
! 	putchar('"');
      }
      else
! 	printf("%s", zlecmds[cmd].name);
      if (clearflag)
! 	putchar('\r'), tcmultout(TCUP, TCMULTUP, nlnct);
      else
! 	putchar('\n');
  }
  
  static int func, funcfound;
--- 1069,1084 ----
  	    buf[1] = '\0';
  	    cky = (Key) gethnode(buf, xbindtab);
  	}
! 	fputc('"', shout);
  	printbind(cky->str, cky->len);
! 	putc('"', shout);
      }
      else
! 	fprintf(shout, "%s", zlecmds[cmd].name);
      if (clearflag)
! 	putc('\r', shout), tcmultout(TCUP, TCMULTUP, nlnct);
      else
! 	putc('\n', shout);
  }
  
  static int func, funcfound;
***************
*** 1070,1077 ****
      if (k->func != func || funcfound >= MAXFOUND || len <= 1)
  	return;
      if (!funcfound++)
! 	printf(" on");
!     putchar(' ');
      printbind(str, len);
  }
  
--- 1092,1099 ----
      if (k->func != func || funcfound >= MAXFOUND || len <= 1)
  	return;
      if (!funcfound++)
! 	fprintf(shout, " on");
!     putc(' ', shout);
      printbind(str, len);
  }
  
***************
*** 1089,1114 ****
  		 (isset(ALWAYSLASTPROMPT) && mult == 1)) ||
  	(unset(ALWAYSLASTPROMPT) && mult != 1);
      if (func == z_selfinsert)
! 	printf("%s is on many keys", zlecmds[func].name);
      else {
! 	printf("%s is", zlecmds[func].name);
  	for (i = 0; funcfound < MAXFOUND && i < 256; i++)
  	    if (mainbindtab[i] == func) {
  		char ch = i;
  		if (!funcfound++)
! 		    printf(" on");
! 		putchar(' ');
  		printbind(&ch, 1);
  	    }
  	if (funcfound < MAXFOUND)
  	    listhtable(xbindtab, (HFunc) printfuncbind);
  	if (!funcfound)
! 	    printf(" not bound to any key");
      }
      if (clearflag)
! 	putchar('\r'), tcmultout(TCUP, TCMULTUP, nlnct);
      else
! 	putchar('\n');
  }
  
  /**/
--- 1111,1136 ----
  		 (isset(ALWAYSLASTPROMPT) && mult == 1)) ||
  	(unset(ALWAYSLASTPROMPT) && mult != 1);
      if (func == z_selfinsert)
! 	fprintf(shout, "%s is on many keys", zlecmds[func].name);
      else {
! 	fprintf(shout, "%s is", zlecmds[func].name);
  	for (i = 0; funcfound < MAXFOUND && i < 256; i++)
  	    if (mainbindtab[i] == func) {
  		char ch = i;
  		if (!funcfound++)
! 		    fprintf(shout, " on");
! 		putc(' ', shout);
  		printbind(&ch, 1);
  	    }
  	if (funcfound < MAXFOUND)
  	    listhtable(xbindtab, (HFunc) printfuncbind);
  	if (!funcfound)
! 	    fprintf(shout, " not bound to any key");
      }
      if (clearflag)
! 	putc('\r', shout), tcmultout(TCUP, TCMULTUP, nlnct);
      else
! 	putc('\n', shout);
  }
  
  /**/
***************
*** 1123,1130 ****
  	    clearflag = 0;
  	}
  	if (postedit)
! 	    printf("%s", postedit);
! 	fflush(stdout);
  	resetneeded = 1;
  	settyinfo(&shttyinfo);
      }
--- 1145,1152 ----
  	    clearflag = 0;
  	}
  	if (postedit)
! 	    fprintf(shout, "%s", postedit);
! 	fflush(shout);
  	resetneeded = 1;
  	settyinfo(&shttyinfo);
      }
*** Src/zle_misc.c.tty	Fri May 19 10:11:05 1995
--- Src/zle_misc.c	Tue May 23 14:20:33 1995
***************
*** 680,686 ****
  {
      if (termok && !isset(SINGLELINEZLE) && tcstr[cap]) {
  	if (flag == 0) 
! 	    tputs(tcstr[cap], 1, putraw);
  	else {
  	    if (docount) {
  		int  t0;
--- 680,686 ----
  {
      if (termok && !isset(SINGLELINEZLE) && tcstr[cap]) {
  	if (flag == 0) 
! 	    tputs(tcstr[cap], 1, putshout);
  	else {
  	    if (docount) {
  		int  t0;
*** Src/zle_refresh.c.tty	Fri May 19 10:11:08 1995
--- Src/zle_refresh.c	Tue May 23 14:23:24 1995
***************
*** 194,204 ****
          if (isset(SINGLELINEZLE) || !termok)
              vcs = 0;
          else if (pptlen && !clearflag) {
!             fwrite(pptbuf, pptlen, 1, stdout);
! 	    fflush(stdout);
  	}
  	if (clearflag)
! 	    putchar('\r'), vcs = 0, moveto(0, pptw);
  	clearf = clearflag;
      } else if (winw != columns)
  	resetvideo();
--- 194,204 ----
          if (isset(SINGLELINEZLE) || !termok)
              vcs = 0;
          else if (pptlen && !clearflag) {
!             fwrite(pptbuf, pptlen, 1, shout);
! 	    fflush(shout);
  	}
  	if (clearflag)
! 	    putc('\r', shout), vcs = 0, moveto(0, pptw);
  	clearf = clearflag;
      } else if (winw != columns)
  	resetvideo();
***************
*** 338,344 ****
      /* output the right-prompt if appropriate */
  	if (put_rpmpt && !ln && !oput_rpmpt) {
  	    moveto(0, winw - 1 - rpw);
! 	    fwrite(pptbuf, pptlen, 1, stdout);
  	    vcs = winw - 1;
  	/* reset character attributes to that set by the main prompt */
  	    txtchange = pmpt_attr;
--- 338,344 ----
      /* output the right-prompt if appropriate */
  	if (put_rpmpt && !ln && !oput_rpmpt) {
  	    moveto(0, winw - 1 - rpw);
! 	    fwrite(pptbuf, pptlen, 1, shout);
  	    vcs = winw - 1;
  	/* reset character attributes to that set by the main prompt */
  	    txtchange = pmpt_attr;
***************
*** 398,404 ****
      oput_rpmpt = put_rpmpt;
      if (nlnct > vmaxln)
  	vmaxln = nlnct;
!     fflush(stdout);		/* make sure everything is written out */
  }
  
  #define tcinscost(X)   (tccan(TCMULTINS) ? tclen[TCMULTINS] : (X)*tclen[TCINS])
--- 398,404 ----
      oput_rpmpt = put_rpmpt;
      if (nlnct > vmaxln)
  	vmaxln = nlnct;
!     fflush(shout);		/* make sure everything is written out */
  }
  
  #define tcinscost(X)   (tccan(TCMULTINS) ? tclen[TCMULTINS] : (X)*tclen[TCINS])
***************
*** 495,501 ****
  	if (!*ol) {
  	    i = (col_cleareol != -1) ? col_cleareol : nllen;
  	    i -= ccs;
! 	    fwrite(nl, i, 1, stdout);
  	    SELECT_ADD_COST(i);
  	    vcs += i;
  	    if (col_cleareol != -1) {
--- 495,501 ----
  	if (!*ol) {
  	    i = (col_cleareol != -1) ? col_cleareol : nllen;
  	    i -= ccs;
! 	    fwrite(nl, i, 1, shout);
  	    SELECT_ADD_COST(i);
  	    vcs += i;
  	    if (col_cleareol != -1) {
***************
*** 535,541 ****
  		    if (tcinscost(i) < pfxlen(p1, ol)) {
  			tc_inschars(i);
  			SELECT_ADD_COST(2 * i);
! 			fwrite(nl, i, 1, stdout);
  			ccs = (vcs += i);
  			nl = p1;
  			break;
--- 535,541 ----
  		    if (tcinscost(i) < pfxlen(p1, ol)) {
  			tc_inschars(i);
  			SELECT_ADD_COST(2 * i);
! 			fwrite(nl, i, 1, shout);
  			ccs = (vcs += i);
  			nl = p1;
  			break;
***************
*** 546,552 ****
  	}
      /* we can't do any fancy tricks, so just dump the single character
         and keep on trying */
! 	putchar(*nl);
  	SELECT_ADD_COST(1);
  	nl++, ol++;
  	ccs++, vcs++;
--- 546,552 ----
  	}
      /* we can't do any fancy tricks, so just dump the single character
         and keep on trying */
! 	putc(*nl, shout);
  	SELECT_ADD_COST(1);
  	nl++, ol++;
  	ccs++, vcs++;
***************
*** 565,575 ****
  
      if (vcs == winw) {
  	if (!hasam) {
! 	    putchar('\r');
! 	    putchar('\n');
  	    SELECT_ADD_COST(2);
  	} else {
! 	    putchar(am_char);
  	    tcout(TCLEFT);
  	    SELECT_ADD_COST(1 + tclen[TCLEFT]);
  	}
--- 565,575 ----
  
      if (vcs == winw) {
  	if (!hasam) {
! 	    putc('\r', shout);
! 	    putc('\n', shout);
  	    SELECT_ADD_COST(2);
  	} else {
! 	    putc(am_char, shout);
  	    tcout(TCLEFT);
  	    SELECT_ADD_COST(1 + tclen[TCLEFT]);
  	}
***************
*** 597,606 ****
  		vln = ln;
  		continue;
  	    }
! 	putchar('\r'), vcs = 0; /* safety precaution */
  	SELECT_ADD_COST(1);
  	while (ln > vln) {
! 	    putchar('\n');
  	    SELECT_ADD_COST(1);
  	    vln++;
  	}
--- 597,606 ----
  		vln = ln;
  		continue;
  	    }
! 	putc('\r', shout), vcs = 0; /* safety precaution */
  	SELECT_ADD_COST(1);
  	while (ln > vln) {
! 	    putc('\n', shout);
  	    SELECT_ADD_COST(1);
  	    vln++;
  	}
***************
*** 608,614 ****
  /* choose cheapest movements for ttys without multiple movement capabilities -
     do this now because it's easier (to code) */
      if (cl <= vcs / 2) {
! 	putchar('\r');
  	SELECT_ADD_COST(1);
  	vcs = 0;
      }
--- 608,614 ----
  /* choose cheapest movements for ttys without multiple movement capabilities -
     do this now because it's easier (to code) */
      if (cl <= vcs / 2) {
! 	putc('\r', shout);
  	SELECT_ADD_COST(1);
  	vcs = 0;
      }
***************
*** 690,698 ****
      for (j = 0, t = nbuf[vln]; *t && (j < i); j++, t++);
      if (j == i)
  	for ( ; *t && ct; ct--, t++)
! 	    putchar(*t);
      while (ct--)
! 	putchar(' ');		/* not my fault your terminal can't go right */
  }
  
  /**/
--- 690,698 ----
      for (j = 0, t = nbuf[vln]; *t && (j < i); j++, t++);
      if (j == i)
  	for ( ; *t && ct; ct--, t++)
! 	    putc(*t, shout);
      while (ct--)
! 	putc(' ', shout);	/* not my fault your terminal can't go right */
  }
  
  /**/
***************
*** 704,711 ****
      if (ct && !tcmultout(TCDOWN, TCMULTDOWN, ct)) {
  	SELECT_ADD_COST(ct + 1);
  	while (ct--)
! 	    putchar('\n');
! 	putchar('\r'), ret = -1;
      }
      return ret;
  }
--- 704,711 ----
      if (ct && !tcmultout(TCDOWN, TCMULTDOWN, ct)) {
  	SELECT_ADD_COST(ct + 1);
  	while (ct--)
! 	    putc('\n', shout);
! 	putc('\r', shout), ret = -1;
      }
      return ret;
  }
***************
*** 713,729 ****
  /* I'm NOT going to worry about padding unless anyone complains. */
  
  /**/
  void
  tcout(int cap)
  {
!     tputs(tcstr[cap], 1, putraw);
  }
  
  /**/
  void
  tcoutarg(int cap, int arg)
  {
!     tputs(tgoto(tcstr[cap], arg, arg), 1, putraw);
  }
  
  /**/
--- 713,737 ----
  /* I'm NOT going to worry about padding unless anyone complains. */
  
  /**/
+ int
+ putshout(int c)
+ {
+     putc(c, shout);
+     return 0;
+ }
+ 
+ /**/
  void
  tcout(int cap)
  {
!     tputs(tcstr[cap], 1, putshout);
  }
  
  /**/
  void
  tcoutarg(int cap, int arg)
  {
!     tputs(tgoto(tcstr[cap], arg, arg), 1, putshout);
  }
  
  /**/
***************
*** 740,746 ****
  redisplay(void)
  {
      moveto(0, pptw);
!     putchar('\r');
      resetneeded = 1;
      clearflag = 0;
  }
--- 748,754 ----
  redisplay(void)
  {
      moveto(0, pptw);
!     putc('\r', shout);
      resetneeded = 1;
      clearflag = 0;
  }
***************
*** 818,824 ****
  
  	if (!*refreshop) {
  	    if ((t0 = strlen(vp)))
! 		fwrite(vp, t0, 1, stdout);
  	    vcs += t0;
  	    break;
  	}
--- 826,832 ----
  
  	if (!*refreshop) {
  	    if ((t0 = strlen(vp)))
! 		fwrite(vp, t0, 1, shout);
  	    vcs += t0;
  	    break;
  	}
***************
*** 827,836 ****
  		tcout(TCCLEAREOL);
  	    else
  		for (; *refreshop++; vcs++)
! 		    putchar(' ');
  	    break;
  	}
! 	putchar(*vp);
  	vcs++, t0++;
  	vp++, refreshop++;
      }
--- 835,844 ----
  		tcout(TCCLEAREOL);
  	    else
  		for (; *refreshop++; vcs++)
! 		    putc(' ', shout);
  	    break;
  	}
! 	putc(*vp, shout);
  	vcs++, t0++;
  	vp++, refreshop++;
      }
***************
*** 840,846 ****
      qbuf = nbuf;
      nbuf = obuf;
      obuf = qbuf;
!     fflush(stdout);		/* make sure everything is written out */
  }
  
  /**/
--- 848,854 ----
      qbuf = nbuf;
      nbuf = obuf;
      obuf = qbuf;
!     fflush(shout);		/* make sure everything is written out */
  }
  
  /**/
***************
*** 850,856 ****
      if (pos == vcs)
  	return;
      if (pos <= vcs / 2) {
! 	putchar('\r');
  	vcs = 0;
      }
      if (pos < vcs) {
--- 858,864 ----
      if (pos == vcs)
  	return;
      if (pos <= vcs / 2) {
! 	putc('\r', shout);
  	vcs = 0;
      }
      if (pos < vcs) {
***************
*** 862,868 ****
  	    vcs = pos;
  	else
  	    while (pos > vcs) {
! 		putchar(nbuf[0][vcs]);
  		vcs++;
  	    }
      }
--- 870,876 ----
  	    vcs = pos;
  	else
  	    while (pos > vcs) {
! 		putc(nbuf[0][vcs], shout);
  		vcs++;
  	    }
      }
*** Src/zle_tricky.c.tty	Fri May 19 10:11:13 1995
--- Src/zle_tricky.c	Tue May 23 14:20:34 1995
***************
*** 2981,2987 ****
  
  	if (clearflag)
  	    tcmultout(TCUP, TCMULTUP, up + nlnct);
! 	fflush(stdout);
      }
      ll = strlen((char *)line);
      if (cs > ll)
--- 2981,2987 ----
  
  	if (clearflag)
  	    tcmultout(TCUP, TCMULTUP, up + nlnct);
! 	fflush(shout);
      }
      ll = strlen((char *)line);
      if (cs > ll)
***************
*** 3401,3413 ****
  		switch (*p) {
  		case '%':
  		    if (dopr)
! 			putchar('%');
  		    cc++;
  		    break;
  		case 'n':
  		    sprintf(nc, "%d", n);
  		    if (dopr)
! 			printf(nc);
  		    cc += strlen(nc);
  	    } else
  		break;
--- 3401,3413 ----
  		switch (*p) {
  		case '%':
  		    if (dopr)
! 			putc('%', shout);
  		    cc++;
  		    break;
  		case 'n':
  		    sprintf(nc, "%d", n);
  		    if (dopr)
! 			fprintf(shout, nc);
  		    cc += strlen(nc);
  	    } else
  		break;
***************
*** 3418,3428 ****
  		cc = 0;
  	    }
  	    if (dopr)
! 		putchar(*p);
  	}
      }
      if (dopr)
! 	putchar('\n');
  
      return l + (cc / columns);
  }
--- 3418,3428 ----
  		cc = 0;
  	    }
  	    if (dopr)
! 		putc(*p, shout);
  	}
      }
      if (dopr)
! 	putc('\n', shout);
  
      return l + (cc / columns);
  }
***************
*** 3492,3515 ****
      /* Maybe we have to ask if the user wants to see the list. */
      if ((listmax && ct > listmax) || (!listmax && up >= lines)) {
  	setterm();
! 	fprintf(stdout, "zsh: do you wish to see all %d possibilities? ", ct);
! 	fflush(stdout);
  	if (getzlequery() != 'y') {
  	    if (clearflag) {
! 		putchar('\r');
  		if (tccan(TCCLEAREOD))
  		    tcout(TCCLEAREOD);
  		tcmultout(TCUP, TCMULTUP, nlnct);
  	    } else
! 		putchar('\n');
  	    return;
  	}
  	if (clearflag) {
! 	    putchar('\r');
  	    if (tccan(TCCLEAREOD))
  		tcout(TCCLEAREOD);
  	} else
! 	    putchar('\n');
  	settyinfo(&shttyinfo);
      }
      /* After the query, the explanation string was deleted, print it
--- 3492,3515 ----
      /* Maybe we have to ask if the user wants to see the list. */
      if ((listmax && ct > listmax) || (!listmax && up >= lines)) {
  	setterm();
! 	fprintf(shout, "zsh: do you wish to see all %d possibilities? ", ct);
! 	fflush(shout);
  	if (getzlequery() != 'y') {
  	    if (clearflag) {
! 		putc('\r', shout);
  		if (tccan(TCCLEAREOD))
  		    tcout(TCCLEAREOD);
  		tcmultout(TCUP, TCMULTUP, nlnct);
  	    } else
! 		putc('\n', shout);
  	    return;
  	}
  	if (clearflag) {
! 	    putc('\r', shout);
  	    if (tccan(TCCLEAREOD))
  		tcout(TCCLEAREOD);
  	} else
! 	    putc('\n', shout);
  	settyinfo(&shttyinfo);
      }
      /* After the query, the explanation string was deleted, print it
***************
*** 3532,3556 ****
  		if (ispattern) {
  		    sav = ap[0][t2 - boff];
  		    ap[0][t2 - boff] = '\0';
! 		    printf("%s", *ap + off);
  		    ap[0][t2 - boff] = sav;
  		    pb = *ap;
  		    t2 -= off + boff - 1;
  		} else {
! 		    printf("%s%s%s", fpre, *ap, fsuf);
  		    sprintf(pb = pbuf, "%s%s%s%s",
  			    (prpre && *prpre) ? prpre : "./", fpre, *ap, fsuf);
  		}
  		if (ztat(pb, &buf, 1))
! 		    putchar(' ');
  		else
  		    /* Print the file type character. */
! 		    putchar(file_type(buf.st_mode));
  		for (t0 = colsz; t0 && *ap; t0--, ap++);
  		if (*ap)
  		    /* And add spaces to make the columns aligned. */
  		    for (; t2 < fw; t2++)
! 			putchar(' ');
  	    }
  	} else
  	    while (*ap) {
--- 3532,3556 ----
  		if (ispattern) {
  		    sav = ap[0][t2 - boff];
  		    ap[0][t2 - boff] = '\0';
! 		    fprintf(shout, "%s", *ap + off);
  		    ap[0][t2 - boff] = sav;
  		    pb = *ap;
  		    t2 -= off + boff - 1;
  		} else {
! 		    fprintf(shout, "%s%s%s", fpre, *ap, fsuf);
  		    sprintf(pb = pbuf, "%s%s%s%s",
  			    (prpre && *prpre) ? prpre : "./", fpre, *ap, fsuf);
  		}
  		if (ztat(pb, &buf, 1))
! 		    putc(' ', shout);
  		else
  		    /* Print the file type character. */
! 		    putc(file_type(buf.st_mode), shout);
  		for (t0 = colsz; t0 && *ap; t0--, ap++);
  		if (*ap)
  		    /* And add spaces to make the columns aligned. */
  		    for (; t2 < fw; t2++)
! 			putc(' ', shout);
  	    }
  	} else
  	    while (*ap) {
***************
*** 3560,3582 ****
  		if (ispattern) {
  		    sav = ap[0][t2 - boff];
  		    ap[0][t2 - boff] = '\0';
! 		    printf("%s", *ap + off);
  		    ap[0][t2 - boff] = sav;
  		    t2 -= off + boff;
  		} else if (!(haswhat & HAS_MISC)) {
! 		    printf("%s%s%s", fpre, *ap, fsuf);
  		    t2 += fpl + fsl;
  		} else {
! 		    printf("%s%s%s", lpre, *ap, lsuf);
  		    t2 += lpl + lsl;
  		}
  		for (t0 = colsz; t0 && *ap; t0--, ap++);
  		if (*ap)
  		    for (; t2 < fw; t2++)
! 			putchar(' ');
  	    }
  	if (t1 != colsz - 1 || !clearflag)
! 	    putchar('\n');
      }
      if (clearflag)
  	/* Move the cursor up to the prompt, if always_last_prompt is set
--- 3560,3582 ----
  		if (ispattern) {
  		    sav = ap[0][t2 - boff];
  		    ap[0][t2 - boff] = '\0';
! 		    fprintf(shout, "%s", *ap + off);
  		    ap[0][t2 - boff] = sav;
  		    t2 -= off + boff;
  		} else if (!(haswhat & HAS_MISC)) {
! 		    fprintf(shout, "%s%s%s", fpre, *ap, fsuf);
  		    t2 += fpl + fsl;
  		} else {
! 		    fprintf(shout, "%s%s%s", lpre, *ap, lsuf);
  		    t2 += lpl + lsl;
  		}
  		for (t0 = colsz; t0 && *ap; t0--, ap++);
  		if (*ap)
  		    for (; t2 < fw; t2++)
! 			putc(' ', shout);
  	    }
  	if (t1 != colsz - 1 || !clearflag)
! 	    putc('\n', shout);
      }
      if (clearflag)
  	/* Move the cursor up to the prompt, if always_last_prompt is set
***************
*** 3584,3594 ****
  	if (up < lines)
  	    tcmultout(TCUP, TCMULTUP, up);
  	else
! 	    clearflag = 0, putchar('\n');
  
      expl = NULL;
  
!     fflush(stdout);
  }
  
  /* A list printing function, used for COMP_LIST_COMPLETE, it sorts the
--- 3584,3594 ----
  	if (up < lines)
  	    tcmultout(TCUP, TCMULTUP, up);
  	else
! 	    clearflag = 0, putc('\n', shout);
  
      expl = NULL;
  
!     fflush(shout);
  }
  
  /* A list printing function, used for COMP_LIST_COMPLETE, it sorts the
*** Src/zle_utils.c.tty	Fri May 19 10:11:14 1995
--- Src/zle_utils.c	Tue May 23 14:20:34 1995
***************
*** 300,306 ****
      /* check for typeahead, which is treated as a negative response */
      ioctl(SHTTY, FIONREAD, (char *)&val);
      if (val) {
! 	putchar('n');
  	return 'n';
      }
  #endif
--- 300,306 ----
      /* check for typeahead, which is treated as a negative response */
      ioctl(SHTTY, FIONREAD, (char *)&val);
      if (val) {
! 	putc('n', shout);
  	return 'n';
      }
  #endif
***************
*** 315,320 ****
  	c = tulower(c);
  
      /* echo response and return */
!     putchar(c);
      return (int)c;
  }
--- 315,320 ----
  	c = tulower(c);
  
      /* echo response and return */
!     putc(c, shout);
      return (int)c;
  }

-- 
Peter Stephenson <P.Stephenson@xxxxxxxxxxxxx>  Tel: +44 1792 205678 extn. 4461
WWW:  http://python.swan.ac.uk/~pypeters/      Fax: +44 1792 295324
Department of Physics, University of Wales, Swansea,
Singleton Park, Swansea, SA2 8PP, U.K.



Messages sorted by: Reverse Date, Date, Thread, Author