xref: /freebsd/contrib/tcsh/ed.init.c (revision 4f29da19bd44f0e99f021510460a81bf754c21d2)
1 /* $Header: /src/pub/tcsh/ed.init.c,v 3.52 2005/01/18 20:24:50 christos Exp $ */
2 /*
3  * ed.init.c: Editor initializations
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTS_ION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include "sh.h"
34 
35 RCSID("$Id: ed.init.c,v 3.52 2005/01/18 20:24:50 christos Exp $")
36 
37 #include "ed.h"
38 #include "tc.h"
39 #include "ed.defns.h"
40 
41 /* ed.init.c -- init routines for the line editor */
42 /* #define DEBUG_TTY */
43 
44 int     Tty_raw_mode = 0;	/* Last tty change was to raw mode */
45 int     MacroLvl = -1;		/* pointer to current macro nesting level; */
46 				/* (-1 == none) */
47 static int Tty_quote_mode = 0;	/* Last tty change was to quote mode */
48 static unsigned char vdisable;	/* The value of _POSIX_VDISABLE from
49 				 * pathconf(2) */
50 
51 int     Tty_eight_bit = -1;	/* does the tty handle eight bits */
52 
53 extern int GotTermCaps;
54 
55 static ttydata_t extty, edtty, tstty;
56 #define qutty tstty
57 
58 #define SHTTY (insource ? OLDSTD : SHIN)
59 
60 #define uc unsigned char
61 static unsigned char ttychars[NN_IO][C_NCC] = {
62     {
63 	(uc)CINTR,	(uc)CQUIT, 	 (uc)CERASE, 	   (uc)CKILL,
64 	(uc)CEOF, 	(uc)CEOL, 	 (uc)CEOL2, 	   (uc)CSWTCH,
65 	(uc)CDSWTCH,	(uc)CERASE2,	 (uc)CSTART, 	   (uc)CSTOP,
66 	(uc)CWERASE, 	(uc)CSUSP, 	 (uc)CDSUSP, 	   (uc)CREPRINT,
67 	(uc)CDISCARD, 	(uc)CLNEXT,	 (uc)CSTATUS,	   (uc)CPAGE,
68 	(uc)CPGOFF,	(uc)CKILL2, 	 (uc)CBRK, 	   (uc)CMIN,
69 	(uc)CTIME
70     },
71     {
72 	CINTR, 		 CQUIT, 	  CERASE, 	   CKILL,
73 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
74 	_POSIX_VDISABLE, CERASE2,	  CSTART, 	   CSTOP,
75 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
76 	CDISCARD, 	 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
77 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
78 	0
79     },
80     {
81 	0,		 0,		  0,		   0,
82 	0,		 0,		  0,		   0,
83 	0,		 0,		  0,		   0,
84 	0,		 0,		  0,		   0,
85 	0,		 0,		  0,		   0,
86 	0,		 0,		  0,		   0,
87 	0
88     }
89 };
90 
91 #ifdef SIG_WINDOW
92 void
93 check_window_size(force)
94     int     force;
95 {
96 #ifdef BSDSIGS
97     sigmask_t omask;
98 #endif /* BSDSIGS */
99     int     lins, cols;
100 
101     /* don't want to confuse things here */
102 #ifdef BSDSIGS
103     omask = sigblock(sigmask(SIG_WINDOW)) & ~sigmask(SIG_WINDOW);
104 #else /* BSDSIGS */
105     (void) sighold(SIG_WINDOW);
106 #endif /* BSDSIGS */
107     /*
108      * From: bret@shark.agps.lanl.gov (Bret Thaeler) Avoid sunview bug, where a
109      * partially hidden window gets a SIG_WINDOW every time the text is
110      * scrolled
111      */
112     if (GetSize(&lins, &cols) || force) {
113 	if (GettingInput) {
114 	    ClearLines();
115 	    ClearDisp();
116 	    MoveToLine(0);
117 	    MoveToChar(0);
118 	    ChangeSize(lins, cols);
119 	    Refresh();
120 	}
121 	else
122 	    ChangeSize(lins, cols);
123     }
124 #ifdef BSDSIGS
125     (void) sigsetmask(omask);	/* can change it again */
126 #else				/* BSDSIGS */
127     (void) sigrelse(SIG_WINDOW);
128 #endif /* BSDSIGS */
129     windowchg = 0;
130 }
131 
132 RETSIGTYPE
133 /*ARGSUSED*/
134 window_change(snum)
135 int snum;
136 {
137     USE(snum);
138 #ifdef UNRELSIGS
139     /* If we were called as a signal handler, restore it. */
140     if (snum > 0)
141       sigset(snum, window_change);
142 #endif /* UNRELSIGS */
143     windowchg = 1;
144 }
145 
146 #endif /* SIG_WINDOW */
147 
148 void
149 ed_set_tty_eight_bit()
150 {
151     if (tty_getty(SHTTY, &extty) == -1) {
152 #ifdef DEBUG_TTY
153 	xprintf("ed_set_tty_eight_bit: tty_getty: %s\n", strerror(errno));
154 #endif /* DEBUG_TTY */
155 	return;
156     }
157     Tty_eight_bit = tty_geteightbit(&extty);
158 }
159 
160 
161 int
162 ed_Setup(rst)
163     int rst;
164 {
165     static int havesetup = 0;
166     struct varent *imode;
167 
168     if (havesetup) 	/* if we have never been called */
169 	return(0);
170 
171 #if defined(POSIX) && defined(_PC_VDISABLE) && !defined(BSD4_4) && \
172     !defined(WINNT_NATIVE)
173     {
174 	long pcret;
175 
176 	if ((pcret = fpathconf(SHTTY, _PC_VDISABLE)) == -1L)
177 	    vdisable = (unsigned char) _POSIX_VDISABLE;
178 	else
179 	    vdisable = (unsigned char) pcret;
180 	if (vdisable != (unsigned char) _POSIX_VDISABLE && rst != 0)
181 	    for (rst = 0; rst < C_NCC; rst++) {
182 		if (ttychars[ED_IO][rst] == (unsigned char) _POSIX_VDISABLE)
183 		    ttychars[ED_IO][rst] = vdisable;
184 		if (ttychars[EX_IO][rst] == (unsigned char) _POSIX_VDISABLE)
185 		    ttychars[EX_IO][rst] = vdisable;
186 	    }
187     }
188 #else /* ! POSIX || !_PC_VDISABLE || BSD4_4 || WINNT_NATIVE */
189     vdisable = (unsigned char) _POSIX_VDISABLE;
190 #endif /* POSIX && _PC_VDISABLE && !BSD4_4 && !WINNT_NATIVE */
191 
192     if ((imode = adrof(STRinputmode)) != NULL && imode->vec != NULL) {
193 	if (!Strcmp(*(imode->vec), STRinsert))
194 	    inputmode = MODE_INSERT;
195 	else if (!Strcmp(*(imode->vec), STRoverwrite))
196 	    inputmode = MODE_REPLACE;
197     }
198     else
199 	inputmode = MODE_INSERT;
200     ed_InitMaps();
201     Hist_num = 0;
202     Expand = 0;
203     SetKillRing(getn(varval(STRkillring)));
204 
205 #ifndef WINNT_NATIVE
206     if (tty_getty(SHTTY, &extty) == -1) {
207 # ifdef DEBUG_TTY
208 	xprintf("ed_Setup: tty_getty: %s\n", strerror(errno));
209 # endif /* DEBUG_TTY */
210 	return(-1);
211     }
212 
213     tstty = edtty = extty;
214 
215     T_Speed = tty_getspeed(&extty);
216     T_Tabs = tty_gettabs(&extty);
217     Tty_eight_bit = tty_geteightbit(&extty);
218 
219 # if defined(POSIX) || defined(TERMIO)
220     extty.d_t.c_iflag &= ~ttylist[EX_IO][M_INPUT].t_clrmask;
221     extty.d_t.c_iflag |=  ttylist[EX_IO][M_INPUT].t_setmask;
222 
223     extty.d_t.c_oflag &= ~ttylist[EX_IO][M_OUTPUT].t_clrmask;
224     extty.d_t.c_oflag |=  ttylist[EX_IO][M_OUTPUT].t_setmask;
225 
226     extty.d_t.c_cflag &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
227     extty.d_t.c_cflag |=  ttylist[EX_IO][M_CONTROL].t_setmask;
228 
229     extty.d_t.c_lflag &= ~ttylist[EX_IO][M_LINED].t_clrmask;
230     extty.d_t.c_lflag |=  ttylist[EX_IO][M_LINED].t_setmask;
231 
232 #  if defined(IRIX3_3) && SYSVREL < 4
233     extty.d_t.c_line = NTTYDISC;
234 #  endif /* IRIX3_3 && SYSVREL < 4 */
235 
236 # else	/* GSTTY */		/* V7, Berkeley style tty */
237 
238     if (T_Tabs) {	/* order of &= and |= is important to XTABS */
239 	extty.d_t.sg_flags &= ~(ttylist[EX_IO][M_CONTROL].t_clrmask|XTABS);
240 	extty.d_t.sg_flags |=   ttylist[EX_IO][M_CONTROL].t_setmask;
241     }
242     else {
243 	extty.d_t.sg_flags &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
244 	extty.d_t.sg_flags |= (ttylist[EX_IO][M_CONTROL].t_setmask|XTABS);
245     }
246 
247     extty.d_lb &= ~ttylist[EX_IO][M_LOCAL].t_clrmask;
248     extty.d_lb |=  ttylist[EX_IO][M_LOCAL].t_setmask;
249 
250 # endif /* GSTTY */
251     /*
252      * Reset the tty chars to reasonable defaults
253      * If they are disabled, then enable them.
254      */
255     if (rst) {
256 	if (tty_cooked_mode(&tstty)) {
257 	    tty_getchar(&tstty, ttychars[TS_IO]);
258 	    /*
259 	     * Don't affect CMIN and CTIME for the editor mode
260 	     */
261 	    for (rst = 0; rst < C_NCC - 2; rst++)
262 		if (ttychars[TS_IO][rst] != vdisable &&
263 		    ttychars[ED_IO][rst] != vdisable)
264 		    ttychars[ED_IO][rst] = ttychars[TS_IO][rst];
265 	    for (rst = 0; rst < C_NCC; rst++)
266 		if (ttychars[TS_IO][rst] != vdisable &&
267 		    ttychars[EX_IO][rst] != vdisable)
268 		    ttychars[EX_IO][rst] = ttychars[TS_IO][rst];
269 	}
270 	tty_setchar(&extty, ttychars[EX_IO]);
271 	if (tty_setty(SHTTY, &extty) == -1) {
272 # ifdef DEBUG_TTY
273 	    xprintf("ed_Setup: tty_setty: %s\n", strerror(errno));
274 # endif /* DEBUG_TTY */
275 	    return(-1);
276 	}
277     }
278     else
279 	tty_setchar(&extty, ttychars[EX_IO]);
280 
281 # ifdef SIG_WINDOW
282     (void) sigset(SIG_WINDOW, window_change);	/* for window systems */
283 # endif
284 #else /* WINNT_NATIVE */
285 # ifdef DEBUG
286     if (rst)
287 	xprintf("rst received in ed_Setup() %d\n", rst);
288 # endif
289 #endif /* WINNT_NATIVE */
290     havesetup = 1;
291     return(0);
292 }
293 
294 void
295 ed_Init()
296 {
297     ResetInLine(1);		/* reset the input pointers */
298     GettingInput = 0;		/* just in case */
299 #ifdef notdef
300     /* XXX This code was here before the kill ring:
301     LastKill = KillBuf;		/ * no kill buffer * /
302        If there was any reason for that other than to make sure LastKill
303        was initialized, the code below should go in here instead - but
304        it doesn't seem reasonable to lose the entire kill ring (which is
305        "self-initializing") just because you set $term or whatever, so
306        presumably this whole '#ifdef notdef' should just be taken out.  */
307 
308     {				/* no kill ring - why? */
309 	int i;
310 	for (i = 0; i < KillRingMax; i++) {
311 	    if (KillRing[i].buf != NULL)
312 		xfree((ptr_t) KillRing[i].buf);
313 	    KillRing[i].buf = NULL;
314 	    KillRing[i].len = 0;
315 	}
316 	YankPos = KillPos = 0;
317 	KillRingLen = 0;
318     }
319 #endif
320 
321 #ifdef DEBUG_EDIT
322     CheckMaps();		/* do a little error checking on key maps */
323 #endif
324 
325     if (ed_Setup(0) == -1)
326 	return;
327 
328     /*
329      * if we have been called before but GotTermCaps isn't set, our TERM has
330      * changed, so get new termcaps and try again
331      */
332 
333     if (!GotTermCaps)
334 	GetTermCaps();		/* does the obvious, but gets term type each
335 				 * time */
336 
337 #ifndef WINNT_NATIVE
338 # if defined(TERMIO) || defined(POSIX)
339     edtty.d_t.c_iflag &= ~ttylist[ED_IO][M_INPUT].t_clrmask;
340     edtty.d_t.c_iflag |=  ttylist[ED_IO][M_INPUT].t_setmask;
341 
342     edtty.d_t.c_oflag &= ~ttylist[ED_IO][M_OUTPUT].t_clrmask;
343     edtty.d_t.c_oflag |=  ttylist[ED_IO][M_OUTPUT].t_setmask;
344 
345     edtty.d_t.c_cflag &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
346     edtty.d_t.c_cflag |=  ttylist[ED_IO][M_CONTROL].t_setmask;
347 
348     edtty.d_t.c_lflag &= ~ttylist[ED_IO][M_LINED].t_clrmask;
349     edtty.d_t.c_lflag |=  ttylist[ED_IO][M_LINED].t_setmask;
350 
351 
352 #  if defined(IRIX3_3) && SYSVREL < 4
353     edtty.d_t.c_line = NTTYDISC;
354 #  endif /* IRIX3_3 && SYSVREL < 4 */
355 
356 # else /* GSTTY */
357 
358     if (T_Tabs) {	/* order of &= and |= is important to XTABS */
359 	edtty.d_t.sg_flags &= ~(ttylist[ED_IO][M_CONTROL].t_clrmask | XTABS);
360 	edtty.d_t.sg_flags |=   ttylist[ED_IO][M_CONTROL].t_setmask;
361     }
362     else {
363 	edtty.d_t.sg_flags &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
364 	edtty.d_t.sg_flags |= (ttylist[ED_IO][M_CONTROL].t_setmask | XTABS);
365     }
366 
367     edtty.d_lb &= ~ttylist[ED_IO][M_LOCAL].t_clrmask;
368     edtty.d_lb |=  ttylist[ED_IO][M_LOCAL].t_setmask;
369 # endif /* POSIX || TERMIO */
370 
371     tty_setchar(&edtty, ttychars[ED_IO]);
372 #endif /* WINNT_NATIVE */
373 }
374 
375 /*
376  * Check and re-init the line. set the terminal into 1 char at a time mode.
377  */
378 int
379 Rawmode()
380 {
381     if (Tty_raw_mode)
382 	return (0);
383 
384 #ifdef WINNT_NATIVE
385     do_nt_raw_mode();
386 #else /* !WINNT_NATIVE */
387 # ifdef _IBMR2
388     tty_setdisc(SHTTY, ED_IO);
389 # endif /* _IBMR2 */
390 
391     if (tty_getty(SHTTY, &tstty) == -1) {
392 # ifdef DEBUG_TTY
393 	xprintf("Rawmode: tty_getty: %s\n", strerror(errno));
394 # endif /* DEBUG_TTY */
395 	return(-1);
396     }
397 
398     /*
399      * We always keep up with the eight bit setting and the speed of the
400      * tty. But only we only believe changes that are made to cooked mode!
401      */
402 # if defined(POSIX) || defined(TERMIO)
403     Tty_eight_bit = tty_geteightbit(&tstty);
404     T_Speed = tty_getspeed(&tstty);
405 
406 #  ifdef POSIX
407     /*
408      * Fix from: Steven (Steve) B. Green <xrsbg@charney.gsfc.nasa.gov>
409      * Speed was not being set up correctly under POSIX.
410      */
411     if (tty_getspeed(&extty) != T_Speed || tty_getspeed(&edtty) != T_Speed) {
412 	(void) cfsetispeed(&extty.d_t, T_Speed);
413 	(void) cfsetospeed(&extty.d_t, T_Speed);
414 	(void) cfsetispeed(&edtty.d_t, T_Speed);
415 	(void) cfsetospeed(&edtty.d_t, T_Speed);
416     }
417 #  endif /* POSIX */
418 # else /* GSTTY */
419 
420     T_Speed = tty_getspeed(&tstty);
421     Tty_eight_bit = tty_geteightbit(&tstty);
422 
423     if (extty.d_t.sg_ispeed != tstty.d_t.sg_ispeed) {
424 	extty.d_t.sg_ispeed = tstty.d_t.sg_ispeed;
425 	edtty.d_t.sg_ispeed = tstty.d_t.sg_ispeed;
426     }
427 
428     if (extty.d_t.sg_ospeed != tstty.d_t.sg_ospeed) {
429 	extty.d_t.sg_ospeed = tstty.d_t.sg_ospeed;
430 	edtty.d_t.sg_ospeed = tstty.d_t.sg_ospeed;
431     }
432 # endif /* POSIX || TERMIO */
433 
434     if (tty_cooked_mode(&tstty)) {
435 	/*
436 	 * re-test for some things here (like maybe the user typed
437 	 * "stty -tabs"
438 	 */
439 	if (tty_gettabs(&tstty) == 0)
440 	    T_Tabs = 0;
441 	else
442 	    T_Tabs = CanWeTab();
443 
444 # if defined(POSIX) || defined(TERMIO)
445 	extty.d_t.c_cflag  = tstty.d_t.c_cflag;
446 	extty.d_t.c_cflag &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
447 	extty.d_t.c_cflag |=  ttylist[EX_IO][M_CONTROL].t_setmask;
448 
449 	edtty.d_t.c_cflag  = tstty.d_t.c_cflag;
450 	edtty.d_t.c_cflag &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
451 	edtty.d_t.c_cflag |=  ttylist[ED_IO][M_CONTROL].t_setmask;
452 
453 	extty.d_t.c_lflag = tstty.d_t.c_lflag;
454 	extty.d_t.c_lflag &= ~ttylist[EX_IO][M_LINED].t_clrmask;
455 	extty.d_t.c_lflag |=  ttylist[EX_IO][M_LINED].t_setmask;
456 
457 	edtty.d_t.c_lflag = tstty.d_t.c_lflag;
458 	edtty.d_t.c_lflag &= ~ttylist[ED_IO][M_LINED].t_clrmask;
459 	edtty.d_t.c_lflag |=  ttylist[ED_IO][M_LINED].t_setmask;
460 
461 	extty.d_t.c_iflag = tstty.d_t.c_iflag;
462 	extty.d_t.c_iflag &= ~ttylist[EX_IO][M_INPUT].t_clrmask;
463 	extty.d_t.c_iflag |=  ttylist[EX_IO][M_INPUT].t_setmask;
464 
465 	edtty.d_t.c_iflag = tstty.d_t.c_iflag;
466 	edtty.d_t.c_iflag &= ~ttylist[ED_IO][M_INPUT].t_clrmask;
467 	edtty.d_t.c_iflag |=  ttylist[ED_IO][M_INPUT].t_setmask;
468 
469 	extty.d_t.c_oflag = tstty.d_t.c_oflag;
470 	extty.d_t.c_oflag &= ~ttylist[EX_IO][M_OUTPUT].t_clrmask;
471 	extty.d_t.c_oflag |=  ttylist[EX_IO][M_OUTPUT].t_setmask;
472 
473 	edtty.d_t.c_oflag = tstty.d_t.c_oflag;
474 	edtty.d_t.c_oflag &= ~ttylist[ED_IO][M_OUTPUT].t_clrmask;
475 	edtty.d_t.c_oflag |=  ttylist[ED_IO][M_OUTPUT].t_setmask;
476 
477 # else /* GSTTY */
478 
479 	extty.d_t.sg_flags = tstty.d_t.sg_flags;
480 
481 	extty.d_t.sg_flags &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
482 	extty.d_t.sg_flags |=  ttylist[EX_IO][M_CONTROL].t_setmask;
483 
484 	if (T_Tabs)		/* order of &= and |= is important to XTABS */
485 	    extty.d_t.sg_flags &= ~XTABS;
486 	else
487 	    extty.d_t.sg_flags |= XTABS;
488 
489 	extty.d_lb = tstty.d_lb;
490 	extty.d_lb &= ~ttylist[EX_IO][M_LOCAL].t_clrmask;
491 	extty.d_lb |= ttylist[EX_IO][M_LOCAL].t_setmask;
492 
493 	edtty.d_t.sg_flags = extty.d_t.sg_flags;
494 	if (T_Tabs) {	/* order of &= and |= is important to XTABS */
495 	    edtty.d_t.sg_flags &=
496 		    ~(ttylist[ED_IO][M_CONTROL].t_clrmask|XTABS);
497 	    edtty.d_t.sg_flags |=   ttylist[ED_IO][M_CONTROL].t_setmask;
498 	}
499 	else {
500 	    edtty.d_t.sg_flags &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
501 	    edtty.d_t.sg_flags |=
502 		    (ttylist[ED_IO][M_CONTROL].t_setmask|XTABS);
503 	}
504 
505 	edtty.d_lb = tstty.d_lb;
506 	edtty.d_lb &= ~ttylist[ED_IO][M_LOCAL].t_clrmask;
507 	edtty.d_lb |= ttylist[ED_IO][M_LOCAL].t_setmask;
508 
509 # endif /* TERMIO || POSIX */
510 
511 	{
512 	    int i;
513 
514 	    tty_getchar(&tstty, ttychars[TS_IO]);
515 	    /*
516 	     * Check if the user made any changes.
517 	     * If he did, then propagate the changes to the
518 	     * edit and execute data structures.
519 	     */
520 	    for (i = 0; i < C_NCC; i++)
521 		if (ttychars[TS_IO][i] != ttychars[EX_IO][i])
522 		    break;
523 
524 	    if (i != C_NCC || didsetty) {
525 		didsetty = 0;
526 		/*
527 		 * Propagate changes only to the unprotected chars
528 		 * that have been modified just now.
529 		 */
530 		for (i = 0; i < C_NCC; i++) {
531 		    if (!((ttylist[ED_IO][M_CHAR].t_setmask & C_SH(i))) &&
532 			(ttychars[TS_IO][i] != ttychars[EX_IO][i]))
533 			ttychars[ED_IO][i] = ttychars[TS_IO][i];
534 		    if (ttylist[ED_IO][M_CHAR].t_clrmask & C_SH(i))
535 			ttychars[ED_IO][i] = vdisable;
536 		}
537 		tty_setchar(&edtty, ttychars[ED_IO]);
538 
539 		for (i = 0; i < C_NCC; i++) {
540 		    if (!((ttylist[EX_IO][M_CHAR].t_setmask & C_SH(i))) &&
541 			(ttychars[TS_IO][i] != ttychars[EX_IO][i]))
542 			ttychars[EX_IO][i] = ttychars[TS_IO][i];
543 		    if (ttylist[EX_IO][M_CHAR].t_clrmask & C_SH(i))
544 			ttychars[EX_IO][i] = vdisable;
545 		}
546 		tty_setchar(&extty, ttychars[EX_IO]);
547 	    }
548 
549 	}
550     }
551     if (tty_setty(SHTTY, &edtty) == -1) {
552 # ifdef DEBUG_TTY
553 	xprintf("Rawmode: tty_setty: %s\n", strerror(errno));
554 # endif /* DEBUG_TTY */
555 	return(-1);
556     }
557 #endif /* WINNT_NATIVE */
558     Tty_raw_mode = 1;
559     flush();			/* flush any buffered output */
560     return (0);
561 }
562 
563 int
564 Cookedmode()
565 {				/* set tty in normal setup */
566 #ifdef WINNT_NATIVE
567     do_nt_cooked_mode();
568 #else
569     signalfun_t orig_intr;
570 
571 # ifdef _IBMR2
572     tty_setdisc(SHTTY, EX_IO);
573 # endif /* _IBMR2 */
574 
575     if (!Tty_raw_mode)
576 	return (0);
577 
578     /* hold this for reseting tty */
579 # ifdef BSDSIGS
580     orig_intr = (signalfun_t) signal(SIGINT, SIG_IGN);
581 # else
582 #  ifdef SIG_HOLD
583     /*
584      * sigset doesn't return the previous handler if the signal is held,
585      * it will return SIG_HOLD instead. So instead of restoring the
586      * the signal we would end up installing a blocked SIGINT with a
587      * SIG_IGN signal handler. This is what happened when Cookedmode
588      * was called from sched_run, disabling interrupt for the rest
589      * of your session.
590      *
591      * This is what we do:
592      * - if the signal is blocked, keep it that way
593      * - else set it to SIG_IGN
594      *
595      * Casper Dik (casper@fwi.uva.nl)
596      */
597     orig_intr = (signalfun_t) sigset(SIGINT, SIG_HOLD);
598     if (orig_intr != SIG_HOLD)
599 	(void) sigset(SIGINT, SIG_IGN); /* returns SIG_HOLD */
600 #  else /* !SIG_HOLD */
601     /*
602      * No SIG_HOLD; probably no reliable signals as well.
603      */
604     orig_intr = (signalfun_t) sigset(SIGINT, SIG_IGN);
605 #  endif /* SIG_HOLD */
606 # endif /* BSDSIGS */
607     if (tty_setty(SHTTY, &extty) == -1) {
608 # ifdef DEBUG_TTY
609 	xprintf("Cookedmode: tty_setty: %s\n", strerror(errno));
610 # endif /* DEBUG_TTY */
611 	return -1;
612     }
613 # ifdef BSDSIGS
614     (void) signal(SIGINT, orig_intr);	/* take these again */
615 # else
616     (void) sigset(SIGINT, orig_intr);	/* take these again */
617 # endif /* BSDSIGS */
618 #endif /* WINNT_NATIVE */
619 
620     Tty_raw_mode = 0;
621     return (0);
622 }
623 
624 void
625 ResetInLine(macro)
626     int macro;
627 {
628     Cursor = InputBuf;		/* reset cursor */
629     LastChar = InputBuf;
630     InputLim = &InputBuf[INBUFSIZE - 2];
631     Mark = InputBuf;
632     MetaNext = 0;
633     CurrentKeyMap = CcKeyMap;
634     AltKeyMap = 0;
635     Hist_num = 0;
636     DoingArg = 0;
637     Argument = 1;
638     LastCmd = F_UNASSIGNED;	/* previous command executed */
639     if (macro)
640 	MacroLvl = -1;		/* no currently active macros */
641 }
642 
643 static Char *Input_Line = NULL;
644 int
645 Load_input_line()
646 {
647 #ifdef SUNOS4
648     long chrs = 0;
649 #else /* !SUNOS4 */
650     /*
651      * *Everyone* else has an int, but SunOS wants long!
652      * This breaks where int != long (alpha)
653      */
654     int chrs = 0;
655 #endif /* SUNOS4 */
656 
657     if (Input_Line)
658 	xfree((ptr_t) Input_Line);
659     Input_Line = NULL;
660 
661     if (Tty_raw_mode)
662 	return 0;
663 
664 #if defined(FIONREAD) && !defined(OREO)
665     (void) ioctl(SHIN, FIONREAD, (ioctl_t) &chrs);
666     if (chrs > 0) {
667 	char    buf[BUFSIZE];
668 
669 	chrs = read(SHIN, buf, (size_t) min(chrs, BUFSIZE - 1));
670 	if (chrs > 0) {
671 	    buf[chrs] = '\0';
672 	    Input_Line = Strsave(str2short(buf));
673 	    PushMacro(Input_Line);
674 	}
675 #ifdef convex
676         /* need to print errno message in case file is migrated */
677         if (chrs < 0)
678             stderror(ERR_SYSTEM, progname, strerror(errno));
679 #endif
680     }
681 #endif  /* FIONREAD && !OREO */
682     return chrs > 0;
683 }
684 
685 /*
686  * Bugfix (in Swedish) by:
687  * Johan Widen
688  * SICS, PO Box 1263, S-163 13 SPANGA, SWEDEN
689  * {mcvax,munnari,cernvax,diku,inria,prlb2,penet,ukc,unido}!enea!sics.se!jw
690  * Internet: jw@sics.se
691  *
692  * (via Hans J Albertsson (thanks))
693  */
694 void
695 QuoteModeOn()
696 {
697     if (MacroLvl >= 0)
698 	return;
699 
700 #ifndef WINNT_NATIVE
701     qutty = edtty;
702 
703 #if defined(TERMIO) || defined(POSIX)
704     qutty.d_t.c_iflag &= ~ttylist[QU_IO][M_INPUT].t_clrmask;
705     qutty.d_t.c_iflag |=  ttylist[QU_IO][M_INPUT].t_setmask;
706 
707     qutty.d_t.c_oflag &= ~ttylist[QU_IO][M_OUTPUT].t_clrmask;
708     qutty.d_t.c_oflag |=  ttylist[QU_IO][M_OUTPUT].t_setmask;
709 
710     qutty.d_t.c_cflag &= ~ttylist[QU_IO][M_CONTROL].t_clrmask;
711     qutty.d_t.c_cflag |=  ttylist[QU_IO][M_CONTROL].t_setmask;
712 
713     qutty.d_t.c_lflag &= ~ttylist[QU_IO][M_LINED].t_clrmask;
714     qutty.d_t.c_lflag |=  ttylist[QU_IO][M_LINED].t_setmask;
715 #else /* GSTTY */
716     qutty.d_t.sg_flags &= ~ttylist[QU_IO][M_CONTROL].t_clrmask;
717     qutty.d_t.sg_flags |= ttylist[QU_IO][M_CONTROL].t_setmask;
718     qutty.d_lb &= ~ttylist[QU_IO][M_LOCAL].t_clrmask;
719     qutty.d_lb |= ttylist[QU_IO][M_LOCAL].t_setmask;
720 
721 #endif /* TERMIO || POSIX */
722     if (tty_setty(SHTTY, &qutty) == -1) {
723 #ifdef DEBUG_TTY
724 	xprintf("QuoteModeOn: tty_setty: %s\n", strerror(errno));
725 #endif /* DEBUG_TTY */
726 	return;
727     }
728 #endif /* !WINNT_NATIVE */
729     Tty_quote_mode = 1;
730     return;
731 }
732 
733 void
734 QuoteModeOff()
735 {
736     if (!Tty_quote_mode)
737 	return;
738     Tty_quote_mode = 0;
739     if (tty_setty(SHTTY, &edtty) == -1) {
740 #ifdef DEBUG_TTY
741 	xprintf("QuoteModeOff: tty_setty: %s\n", strerror(errno));
742 #endif /* DEBUG_TTY */
743 	return;
744     }
745     return;
746 }
747