From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gatech.edu (gatech.edu [128.61.1.1]) by werple.mira.net.au (8.6.10/8.6.9) with SMTP id BAA11535 for ; Wed, 24 May 1995 01:32:29 +1000 Received: from math (math.skiles.gatech.edu) by gatech.edu with SMTP id AA27739 (5.65c/Gatech-10.0-IDA for ); Tue, 23 May 1995 11:21:07 -0400 Received: by math (5.x/SMI-SVR4) id AA05898; Tue, 23 May 1995 11:18:29 -0400 Resent-Date: Tue, 23 May 95 16:16:25 +0100 Old-Return-Path: Message-Id: <29387.9505231516@pyro.swan.ac.uk> To: zsh-workers@math.gatech.edu (Zsh hackers list) Subject: Terminal I/O handling fix Date: Tue, 23 May 95 16:16:25 +0100 From: P.Stephenson@swansea.ac.uk X-Mts: smtp Resent-Message-Id: <"e8O3G3.0.4S1.4pVml"@math> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/26 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu 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 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.