source: trunk/third/ispell/term.c @ 10334

Revision 10334, 13.6 KB checked in by ghudson, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10333, which included commits to RCS files with non-trunk default branches.
Line 
1#ifndef lint
2static char Rcs_Id[] =
3    "$Id: term.c,v 1.1.1.1 1997-09-03 21:08:10 ghudson Exp $";
4#endif
5
6/*
7 * term.c - deal with termcap, and unix terminal mode settings
8 *
9 * Pace Willisson, 1983
10 *
11 * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 * 3. All modifications to the source code must be clearly marked as
24 *    such.  Binary redistributions based on modified source code
25 *    must be clearly marked as modified versions in the documentation
26 *    and/or other materials provided with the distribution.
27 * 4. All advertising materials mentioning features or use of this software
28 *    must display the following acknowledgment:
29 *      This product includes software developed by Geoff Kuenning and
30 *      other unpaid contributors.
31 * 5. The name of Geoff Kuenning may not be used to endorse or promote
32 *    products derived from this software without specific prior
33 *    written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED.  IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48/*
49 * $Log: not supported by cvs2svn $
50 * Revision 1.48  1994/10/25  05:46:11  geoff
51 * Fix a couple of places where ifdefs were omitted, though apparently
52 * harmlessly.
53 *
54 * Revision 1.47  1994/09/01  06:06:32  geoff
55 * Change erasechar/killchar to uerasechar/ukillchar to avoid
56 * shared-library problems on HP systems.
57 *
58 * Revision 1.46  1994/01/25  07:12:11  geoff
59 * Get rid of all old RCS log lines in preparation for the 3.1 release.
60 *
61 */
62
63#include "config.h"
64#include "ispell.h"
65#include "proto.h"
66#include "msgs.h"
67#ifdef USG
68#include <termio.h>
69#else
70#include <sgtty.h>
71#endif
72#include <signal.h>
73
74void            erase P ((void));
75void            move P ((int row, int col));
76void            inverse P ((void));
77void            normal P ((void));
78void            backup P ((void));
79static int      putch P ((int c));
80void            terminit P ((void));
81SIGNAL_TYPE     done P ((int signo));
82#ifdef SIGTSTP
83static SIGNAL_TYPE onstop P ((int signo));
84#endif /* SIGTSTP */
85void            stop P ((void));
86int             shellescape P ((char * buf));
87#ifdef USESH
88void            shescape P ((char * buf));
89#endif /* USESH */
90
91void erase ()
92    {
93
94    if (cl)
95        tputs (cl, li, putch);
96    else
97        {
98        if (ho)
99            tputs (ho, 100, putch);
100        else if (cm)
101            tputs (tgoto (cm, 0, 0), 100, putch);
102        tputs (cd, li, putch);
103        }
104    }
105
106void move (row, col)
107    int         row;
108    int         col;
109    {
110    tputs (tgoto (cm, col, row), 100, putch);
111    }
112
113void inverse ()
114    {
115    tputs (so, 10, putch);
116    }
117
118void normal ()
119    {
120    tputs (se, 10, putch);
121    }
122
123void backup ()
124    {
125    if (BC)
126        tputs (BC, 1, putch);
127    else
128        (void) putchar ('\b');
129    }
130
131static int putch (c)
132    int                 c;
133    {
134
135    return putchar (c);
136    }
137
138#ifdef USG
139static struct termio    sbuf;
140static struct termio    osbuf;
141#else
142static struct sgttyb    sbuf;
143static struct sgttyb    osbuf;
144#ifdef TIOCSLTC
145static struct ltchars   ltc;
146static struct ltchars   oltc;
147#endif
148#endif
149static int              termchanged = 0;
150static SIGNAL_TYPE      (*oldint) ();
151static SIGNAL_TYPE      (*oldterm) ();
152#ifdef SIGTSTP
153static SIGNAL_TYPE      (*oldttin) ();
154static SIGNAL_TYPE      (*oldttou) ();
155static SIGNAL_TYPE      (*oldtstp) ();
156#endif
157
158void terminit ()
159    {
160#ifdef TIOCPGRP
161    int                 tpgrp;
162#else
163#ifdef TIOCGPGRP
164    int                 tpgrp;
165#endif
166#endif
167#ifdef TIOCGWINSZ
168    struct winsize      wsize;
169#endif /* TIOCGWINSZ */
170
171    tgetent (termcap, getenv ("TERM"));
172    termptr = termstr;
173    BC = tgetstr ("bc", &termptr);
174    cd = tgetstr ("cd", &termptr);
175    cl = tgetstr ("cl", &termptr);
176    cm = tgetstr ("cm", &termptr);
177    ho = tgetstr ("ho", &termptr);
178    nd = tgetstr ("nd", &termptr);
179    so = tgetstr ("so", &termptr);      /* inverse video on */
180    se = tgetstr ("se", &termptr);      /* inverse video off */
181    if ((sg = tgetnum ("sg")) < 0)      /* space taken by so/se */
182        sg = 0;
183    ti = tgetstr ("ti", &termptr);      /* terminal initialization */
184    te = tgetstr ("te", &termptr);      /* terminal termination */
185    co = tgetnum ("co");
186    li = tgetnum ("li");
187#ifdef TIOCGWINSZ
188    if (ioctl (0, TIOCGWINSZ, (char *) &wsize) >= 0)
189        {
190        if (wsize.ws_col != 0)
191            co = wsize.ws_col;
192        if (wsize.ws_row != 0)
193            li = wsize.ws_row;
194        }
195#endif /* TIOCGWINSZ */
196    /*
197     * Let the variables "LINES" and "COLUMNS" override the termcap
198     * entry.  Technically, this is a terminfo-ism, but I think the
199     * vast majority of users will find it pretty handy.
200     */
201    if (getenv ("COLUMNS") != NULL)
202        co = atoi (getenv ("COLUMNS"));
203    if (getenv ("LINES") != NULL)
204        li = atoi (getenv ("LINES"));
205#if MAX_SCREEN_SIZE > 0
206    if (li > MAX_SCREEN_SIZE)
207        li = MAX_SCREEN_SIZE;
208#endif /* MAX_SCREEN_SIZE > 0 */
209#if MAXCONTEXT == MINCONTEXT
210    contextsize = MINCONTEXT;
211#else /* MAXCONTEXT == MINCONTEXT */
212    if (contextsize == 0)
213#ifdef CONTEXTROUNDUP
214        contextsize = (li * CONTEXTPCT + 99) / 100;
215#else /* CONTEXTROUNDUP */
216        contextsize = (li * CONTEXTPCT) / 100;
217#endif /* CONTEXTROUNDUP */
218    if (contextsize > MAXCONTEXT)
219        contextsize = MAXCONTEXT;
220    else if (contextsize < MINCONTEXT)
221        contextsize = MINCONTEXT;
222#endif /* MAX_CONTEXT == MIN_CONTEXT */
223    /*
224     * Insist on 2 lines for the screen header, 2 for blank lines
225     * separating areas of the screen, 2 for word choices, and 2 for
226     * the minimenu, plus however many are needed for context.  If
227     * possible, make the context smaller to fit on the screen.
228     */
229    if (li < contextsize + 8  &&  contextsize > MINCONTEXT)
230        {
231        contextsize = li - 8;
232        if (contextsize < MINCONTEXT)
233            contextsize = MINCONTEXT;
234        }
235    if (li < MINCONTEXT + 8)
236        (void) fprintf (stderr, TERM_C_SMALL_SCREEN, MINCONTEXT + 8);
237
238#ifdef SIGTSTP
239#ifdef TIOCPGRP
240retry:
241#endif /* SIGTSTP */
242#endif /* TIOCPGRP */
243
244#ifdef USG
245    if (!isatty (0))
246        {
247        (void) fprintf (stderr, TERM_C_NO_BATCH);
248        exit (1);
249        }
250    (void) ioctl (0, TCGETA, (char *) &osbuf);
251    termchanged = 1;
252
253    sbuf = osbuf;
254    sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON);
255    sbuf.c_oflag &= ~(OPOST);
256    sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL);
257    sbuf.c_cc[VMIN] = 1;
258    sbuf.c_cc[VTIME] = 1;
259    (void) ioctl (0, TCSETAW, (char *) &sbuf);
260
261    uerasechar = osbuf.c_cc[VERASE];
262    ukillchar = osbuf.c_cc[VKILL];
263
264#endif
265
266#ifdef SIGTSTP
267#ifndef USG
268    (void) sigsetmask (1<<(SIGTSTP-1) | 1<<(SIGTTIN-1) | 1<<(SIGTTOU-1));
269#endif
270#endif
271#ifdef TIOCGPGRP
272    if (ioctl (0, TIOCGPGRP, (char *) &tpgrp) != 0)
273        {
274        (void) fprintf (stderr, TERM_C_NO_BATCH);
275        exit (1);
276        }
277#endif
278#ifdef SIGTSTP
279#ifdef TIOCPGRP
280    if (tpgrp != getpgrp(0)) /* not in foreground */
281        {
282#ifndef USG
283        (void) sigsetmask (1 << (SIGTSTP - 1) | 1 << (SIGTTIN - 1));
284#endif
285        (void) signal (SIGTTOU, SIG_DFL);
286        (void) kill (0, SIGTTOU);
287        /* job stops here waiting for SIGCONT */
288        goto retry;
289        }
290#endif
291#endif
292
293#ifndef USG
294    (void) ioctl (0, TIOCGETP, (char *) &osbuf);
295#ifdef TIOCGLTC
296    (void) ioctl (0, TIOCGLTC, (char *) &oltc);
297#endif
298    termchanged = 1;
299
300    sbuf = osbuf;
301    sbuf.sg_flags &= ~ECHO;
302    sbuf.sg_flags |= TERM_MODE;
303    (void) ioctl (0, TIOCSETP, (char *) &sbuf);
304
305    uerasechar = sbuf.sg_erase;
306    ukillchar = sbuf.sg_kill;
307
308#ifdef TIOCSLTC
309    ltc = oltc;
310    ltc.t_suspc = -1;
311    (void) ioctl (0, TIOCSLTC, (char *) &ltc);
312#endif
313
314#endif /* USG */
315
316    if ((oldint = signal (SIGINT, SIG_IGN)) != SIG_IGN)
317        (void) signal (SIGINT, done);
318    if ((oldterm = signal (SIGTERM, SIG_IGN)) != SIG_IGN)
319        (void) signal (SIGTERM, done);
320
321#ifdef SIGTSTP
322#ifndef USG
323    (void) sigsetmask (0);
324#endif
325    if ((oldttin = signal (SIGTTIN, SIG_IGN)) != SIG_IGN)
326        (void) signal (SIGTTIN, onstop);
327    if ((oldttou = signal (SIGTTOU, SIG_IGN)) != SIG_IGN)
328        (void) signal (SIGTTOU, onstop);
329    if ((oldtstp = signal (SIGTSTP, SIG_IGN)) != SIG_IGN)
330        (void) signal (SIGTSTP, onstop);
331#endif
332    if (ti)
333        tputs (ti, 1, putch);
334    }
335
336/* ARGSUSED */
337SIGNAL_TYPE done (signo)
338    int         signo;
339    {
340    if (tempfile[0] != '\0')
341        (void) unlink (tempfile);
342    if (termchanged)
343        {
344        if (te)
345            tputs (te, 1, putch);
346#ifdef USG
347        (void) ioctl (0, TCSETAW, (char *) &osbuf);
348#else
349        (void) ioctl (0, TIOCSETP, (char *) &osbuf);
350#ifdef TIOCSLTC
351        (void) ioctl (0, TIOCSLTC, (char *) &oltc);
352#endif
353#endif
354        }
355    exit (0);
356    }
357
358#ifdef SIGTSTP
359static SIGNAL_TYPE onstop (signo)
360    int         signo;
361    {
362#ifdef USG
363    (void) ioctl (0, TCSETAW, (char *) &osbuf);
364#else
365    (void) ioctl (0, TIOCSETP, (char *) &osbuf);
366#ifdef TIOCSLTC
367    (void) ioctl (0, TIOCSLTC, (char *) &oltc);
368#endif
369#endif
370    (void) signal (signo, SIG_DFL);
371#ifndef USG
372    (void) sigsetmask (sigblock (0) & ~(1 << (signo - 1)));
373#endif
374    (void) kill (0, signo);
375    /* stop here until continued */
376    (void) signal (signo, onstop);
377#ifdef USG
378    (void) ioctl (0, TCSETAW, (char *) &sbuf);
379#else
380    (void) ioctl (0, TIOCSETP, (char *) &sbuf);
381#ifdef TIOCSLTC
382    (void) ioctl (0, TIOCSLTC, (char *) &ltc);
383#endif
384#endif
385    }
386#endif
387
388void stop ()
389    {
390#ifdef SIGTSTP
391    onstop (SIGTSTP);
392#else
393    /* for System V */
394    move (li - 1, 0);
395    (void) fflush (stdout);
396    if (getenv ("SHELL"))
397        (void) shellescape (getenv ("SHELL"));
398    else
399        (void) shellescape ("sh");
400#endif
401    }
402
403/* Fork and exec a process.  Returns NZ if command found, regardless of
404** command's return status.  Returns zero if command was not found.
405** Doesn't use a shell.
406*/
407#ifndef USESH
408#define NEED_SHELLESCAPE
409#endif /* USESH */
410#ifndef REGEX_LOOKUP
411#define NEED_SHELLESCAPE
412#endif /* REGEX_LOOKUP */
413#ifdef NEED_SHELLESCAPE
414int shellescape (buf)
415    char *      buf;
416    {
417    char *      argv[100];
418    char *      cp = buf;
419    int         i = 0;
420    int         termstat;
421
422    /* parse buf to args (destroying it in the process) */
423    while (*cp != '\0')
424        {
425        while (*cp == ' '  ||  *cp == '\t')
426            ++cp;
427        if (*cp == '\0')
428            break;
429        argv[i++] = cp;
430        while (*cp != ' '  &&  *cp != '\t'  &&  *cp != '\0')
431            ++cp;
432        if (*cp != '\0')
433            *cp++ = '\0';
434        }
435    argv[i] = NULL;
436
437#ifdef USG
438    (void) ioctl (0, TCSETAW, (char *) &osbuf);
439#else
440    (void) ioctl (0, TIOCSETP, (char *) &osbuf);
441#ifdef TIOCSLTC
442    (void) ioctl (0, TIOCSLTC, (char *) &oltc);
443#endif /* TIOCSLTC */
444#endif
445    (void) signal (SIGINT, oldint);
446    (void) signal (SIGTERM, oldterm);
447#ifdef SIGTSTP
448    (void) signal (SIGTTIN, oldttin);
449    (void) signal (SIGTTOU, oldttou);
450    (void) signal (SIGTSTP, oldtstp);
451#endif
452    if ((i = fork ()) == 0)
453        {
454        (void) execvp (argv[0], (char **) argv);
455        _exit (123);            /* Command not found */
456        }
457    else if (i > 0)
458        {
459        while (wait (&termstat) != i)
460            ;
461        termstat = (termstat == (123 << 8)) ? 0 : -1;
462        }
463    else
464        {
465        (void) printf (TERM_C_CANT_FORK);
466        termstat = -1;          /* Couldn't fork */
467        }
468
469    if (oldint != SIG_IGN)
470        (void) signal (SIGINT, done);
471    if (oldterm != SIG_IGN)
472        (void) signal (SIGTERM, done);
473
474#ifdef SIGTSTP
475    if (oldttin != SIG_IGN)
476        (void) signal (SIGTTIN, onstop);
477    if (oldttou != SIG_IGN)
478        (void) signal (SIGTTOU, onstop);
479    if (oldtstp != SIG_IGN)
480        (void) signal (SIGTSTP, onstop);
481#endif
482
483#ifdef USG
484    (void) ioctl (0, TCSETAW, (char *) &sbuf);
485#else
486    (void) ioctl (0, TIOCSETP, (char *) &sbuf);
487#ifdef TIOCSLTC
488    (void) ioctl (0, TIOCSLTC, (char *) &ltc);
489#endif /* TIOCSLTC */
490#endif
491    if (termstat)
492        {
493        (void) printf (TERM_C_TYPE_SPACE);
494        (void) fflush (stdout);
495#ifdef COMMANDFORSPACE
496        i = GETKEYSTROKE ();
497        if (i != ' ' && i != '\n' && i != '\r')
498            (void) ungetc (i, stdin);
499#else
500        while (GETKEYSTROKE () != ' ')
501            ;
502#endif
503        }
504    return (termstat);
505    }
506#endif /* NEED_SHELLESCAPE */
507
508#ifdef  USESH
509void shescape (buf)
510    char *      buf;
511    {
512#ifdef COMMANDFORSPACE
513    int         ch;
514#endif
515
516#ifdef USG
517    (void) ioctl (0, TCSETAW, (char *) &osbuf);
518#else
519    (void) ioctl (0, TIOCSETP, (char *) &osbuf);
520#ifdef TIOCSLTC
521    (void) ioctl (0, TIOCSLTC, (char *) &oltc);
522#endif
523#endif
524    (void) signal (SIGINT, oldint);
525    (void) signal (SIGTERM, oldterm);
526#ifdef SIGTSTP
527    (void) signal (SIGTTIN, oldttin);
528    (void) signal (SIGTTOU, oldttou);
529    (void) signal (SIGTSTP, oldtstp);
530#endif
531
532    (void) system (buf);
533
534    if (oldint != SIG_IGN)
535        (void) signal (SIGINT, done);
536    if (oldterm != SIG_IGN)
537        (void) signal (SIGTERM, done);
538
539#ifdef SIGTSTP
540    if (oldttin != SIG_IGN)
541        (void) signal (SIGTTIN, onstop);
542    if (oldttou != SIG_IGN)
543        (void) signal (SIGTTOU, onstop);
544    if (oldtstp != SIG_IGN)
545        (void) signal (SIGTSTP, onstop);
546#endif
547
548#ifdef USG
549    (void) ioctl (0, TCSETAW, (char *) &sbuf);
550#else
551    (void) ioctl (0, TIOCSETP, (char *) &sbuf);
552#ifdef TIOCSLTC
553    (void) ioctl (0, TIOCSLTC, (char *) &ltc);
554#endif
555#endif
556    (void) printf (TERM_C_TYPE_SPACE);
557    (void) fflush (stdout);
558#ifdef COMMANDFORSPACE
559    ch = GETKEYSTROKE ();
560    if (ch != ' '  &&  ch != '\n'  &&  ch != '\r')
561        (void) ungetc (ch, stdin);
562#else
563    while (GETKEYSTROKE () != ' ')
564        ;
565#endif
566    }
567#endif
Note: See TracBrowser for help on using the repository browser.