"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* @(#)p.c 1.75 21/08/20 Copyright 1985-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)p.c 1.75 21/08/20 Copyright 1985-2021 J. Schilling";
6 #endif
7 /*
8 * Print some files on screen
9 *
10 * Copyright (c) 1985-2021 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/stdio.h>
27 #include <schily/standard.h>
28 #include <schily/stdlib.h>
29 #include <schily/unistd.h>
30 #include <schily/types.h>
31 #include <schily/utypes.h>
32 #include <schily/fcntl.h>
33 #include <schily/string.h>
34 #include <schily/signal.h>
35 #include <schily/sigset.h>
36 #include <schily/termcap.h>
37 #include <schily/libport.h>
38 #include <schily/errno.h>
39 #define ungetch dos_ungetch /* Avoid DOS/curses ungetch() type clash */
40 #include <schily/termios.h>
41 #undef ungetch /* Restore our old value */
42 #include <schily/nlsdefs.h>
43 #include <schily/limits.h> /* for MB_LEN_MAX */
44 #include <schily/ctype.h> /* For isprint() */
45 #include <schily/wchar.h> /* wchar_t */
46 #include <schily/wctype.h> /* For iswprint() */
47 #include <schily/patmatch.h>
48 #define GT_COMERR /* #define comerr gtcomerr */
49 #define GT_ERROR /* #define error gterror */
50 #include <schily/schily.h>
51
52 #define SEARCHSIZE 256
53 #define DEF_PSIZE 24;
54 #define DEF_LWIDTH 80;
55
56 #if MB_LEN_MAX > 1
57 /*
58 * We are on a platform that supports multi byte characters.
59 */
60 #define nextc() nextwc() /* Read next char */
61 #define peekc() peekwc() /* Peek next char */
62 #define getnextch() getnextwch() /* Consume last peeked char */
63 #define ungetch(c) ungetwch(c) /* Unread char back to buffer */
64 #else
65 #define nextc() (--len >= 0 ? (int) *bp++ : \
66 (fill_buf() <= 0 ? (len == 0 ? EOF : -2) : \
67 (len--, (int) *bp++)))
68 #define peekc() (len > 0 ? (int) *bp : \
69 (fill_buf() <= 0 ? (len == 0 ? EOF : -2) : \
70 ((int) *bp)))
71 #define getnextch() (len--, bp++)
72 #define __peekc() (ungetch(nextc()))
73 #endif
74
75 # ifdef USE_V7_TTY
76 struct sgttyb old;
77 struct sgttyb new;
78
79 # else /* USE_V7_TTY */
80
81 #ifdef USE_TERMIOS
82 struct termios old;
83 struct termios new;
84 #endif
85 # endif /* USE_V7_TTY */
86 int tty = -1;
87
88 FILE *f; /* the file being printed */
89 off_t ofpos; /* saved filepos for searching */
90 int lineno; /* current lineno (used for editing) */
91 int colcnt; /* column on screen we are going to print */
92 int linecnt; /* # of lines actually printed on screen */
93 int lwidth; /* length of a line on screen */
94 int lines; /* # of lines until we print a more prompt */
95 int psize; /* # of lines on a page */
96 int supressblank; /* supress multiple blank lines on output */
97 int clear; /* clear screen before displaying page */
98 int dosmode; /* wether to supress ^M^J sequences */
99 BOOL autodos = TRUE; /* whether to automatically detect DOS mode */
100 int endline; /* print a $ at each end of line */
101 int raw; /* do not expand control characters */
102 BOOL raw8; /* Ausgabe ohne ~ */
103 int silent; /* in silent mode there is no more prompt */
104 int tab; /* do nut expand tabs to spaces but to ^I */
105 int visible; /* _^H sequences are visible */
106 int underline; /* do underlining */
107 int ununderline; /* remove underlining */
108 int help; /* print online help */
109 int prvers; /* print version information */
110 BOOL debug; /* misc debug flag */
111 BOOL nobeep; /* be silent on errors */
112 char *filename; /* Filename fuer Ausgabezwecke */
113 int direction; /* direction to step through file list */
114 #define FORWARD 0
115 char *editor;
116 char *shell;
117 int searchnext;
118 #if MB_LEN_MAX > 1
119 wchar_t searchbuf[SEARCHSIZE];
120 #else
121 char searchbuf[SEARCHSIZE];
122 #endif
123 int alt;
124 int *aux;
125 int *state;
126
127 char *so; /* start standout */
128 char *se; /* end standout */
129 char *xso; /* start abstract bold/standout */
130 char *xse; /* end abstract bold/standout */
131 char *us; /* start underline */
132 char *ue; /* end underline */
133 char *md; /* start bold */
134 char *me; /* end attributes */
135 char *ce; /* clear endline */
136 char *cl; /* clear screen */
137 int li; /* lines on screen */
138 int co; /* columns on screen */
139 BOOL am = TRUE; /* automatic margins */
140 BOOL xn; /* newline ignored > 80 */
141 BOOL has_standout;
142 BOOL has_bold;
143 BOOL has_ul;
144 BOOL has_termcap;
145 int standout;
146 int underl;
147
148 /*
149 * As an incomplete multi byte character after a buffer refill
150 * is partially before the begin of the buffer, we need to be
151 * able to store a second character before that. This happens
152 * when peekc() triggered a buffer refill and then ungetch()
153 * is called.
154 */
155 #define P_BUFSIZE ((8*1024)+(2*MB_LEN_MAX))
156 unsigned char mybuf[P_BUFSIZE]; /* Fuer nextc */
157 unsigned char *bp; /* ditto */
158 int len = 0; /* ditto */
159 int clen = 0; /* # of octects in nextwc() multi byte char */
160 int pclen = 0; /* # of octects in peekwc() multi byte char */
161 unsigned char *cp; /* Beginning of multi byte char in buffer */
162 unsigned char *pcp; /* Beginning of peeked multi byte char in buf */
163
164 #ifdef BUFSIZ
165 char buffer[BUFSIZ]; /* our buffer for stdout */
166 #endif
167 char dcl[] = ":::::::::::::::";
168 /* BEGIN CSTYLED */
169 char options[] =
170 "help,version,debug,nobeep,length#,l#,width#,w#,blank,b,clear,c,dos,nodos%0,end,e,raw,r,raw8,silent,s,tab,t,unul,visible,v";
171 /* END CSTYLED */
172
173 BOOL nameprint = FALSE;
174
175 extern unsigned char csize[];
176 extern unsigned char *ctab[];
177
178 extern void init_charset __PR((void));
179
180 LOCAL void tstp __PR((int sig));
181 LOCAL void usage __PR((int exitcode));
182 EXPORT int main __PR((int ac, char **av));
183 LOCAL void page __PR((void));
184 LOCAL int outchar __PR((int c));
185 LOCAL void moreprompt __PR((void));
186 LOCAL BOOL more __PR((void));
187 LOCAL int get_action __PR((void));
188 LOCAL void onlinehelp __PR((void));
189 LOCAL void redraw __PR((void));
190 LOCAL int inchar __PR((void));
191 #if MB_LEN_MAX > 1
192 LOCAL int inwchar __PR((void));
193 #else
194 #define inwchar inchar
195 #endif
196 #ifndef nextc
197 LOCAL int nextc __PR((void));
198 #endif
199 #if MB_LEN_MAX > 1
200 LOCAL int nextwc __PR((void));
201 LOCAL int peekwc __PR((void));
202 #endif
203 #ifndef ungetch
204 LOCAL int ungetch __PR((int c));
205 #endif
206 #if MB_LEN_MAX > 1
207 LOCAL int ungetwch __PR((int c));
208 LOCAL void getnextwch __PR((void));
209 #endif
210 LOCAL int fill_buf __PR((void));
211 LOCAL BOOL read_pattern __PR((void));
212 LOCAL int do_search __PR((void));
213 LOCAL int unul __PR((Uchar *ob, Uchar *ib, int amt));
214 LOCAL void init_termcap __PR((void));
215 LOCAL int oc __PR((int c));
216 LOCAL void start_standout __PR((void));
217 LOCAL void end_standout __PR((void));
218 #ifdef __needed__
219 LOCAL void start_bold __PR((void));
220 #endif
221 LOCAL void end_attr __PR((void));
222 LOCAL void start_xstandout __PR((void));
223 LOCAL void end_xstandout __PR((void));
224 LOCAL void start_ul __PR((void));
225 LOCAL void end_ul __PR((void));
226 LOCAL void clearline __PR((void));
227 LOCAL void clearscreen __PR((void));
228 LOCAL void init_tty_size __PR((void));
229 LOCAL int get_modes __PR((void));
230 LOCAL void set_modes __PR((void));
231 LOCAL void reset_modes __PR((void));
232 LOCAL void fixtty __PR((int sig));
233
234 #ifdef SIGTSTP
235 LOCAL void
236 tstp(sig)
237 int sig;
238 {
239 /* ignore SIGTTOU so we don't get stopped if the shell modifies pgrp */
240 signal(SIGTTOU, SIG_IGN);
241 end_standout();
242 end_attr();
243 end_ul();
244 clearline();
245 reset_modes();
246 signal(SIGTTOU, SIG_DFL);
247
248 signal(SIGTSTP, SIG_DFL);
249 #ifdef OLD
250 #ifdef HAVE_SIGRELSE
251 sigrelse(SIGTSTP);
252 #else
253 (void) sigsetmask(0);
254 #endif
255 #else /* NEW */
256 unblock_sig(SIGTSTP);
257 #endif
258 kill(getpid(), SIGTSTP);
259
260 /* Hier stoppt 'p' */
261
262 set_modes();
263 moreprompt();
264 }
265 #endif
266
267
268 LOCAL void
269 usage(exitcode)
270 int exitcode;
271 {
272 error("Usage: p [options] [file1...filen]\n");
273 error("Options:\n");
274 error("\t-help\t\tprint this online help\n");
275 error("\t-version\tprint version number\n");
276 error("\t-debug\t\tprint additional debug output\n");
277 error("\tlength=#,l=#\tlength of screen (default 24)\n");
278 error("\twidth=#,w=#\twidth of screen (default 80)\n");
279 error("\t-blank,-b\tsupress multiple blank lines on output\n");
280 error("\t-clear,-c\tclear screen before displaying new page\n");
281 error("\t-dos\t\tsupress '\\r' in '\\r\\n'\n");
282 error("\t-nodos\t\tsupress auto detecting the dos mode\n");
283 error("\t-end,-e\t\tprint a $ at each end of line\n");
284 error("\t-raw,-r\t\tdo not expand chars\n");
285 error("\t-raw8\t\tdo not expand 8bit chars\n");
286 error("\t-silent,-s\tdo not prompt for more stuff\n");
287 error("\t-tab,-t\t\tdo not expand tabs to spaces but to ^I\n");
288 #ifdef __needed__
289 error("\t-unul\t\tremove underlining and bold sequences\n");
290 #endif
291 error("\t-visible,-v\tunderlining/bold sequences become visible\n\n");
292 error(" When asked for more: confirm=page, n=no more, h=half page\n");
293 error(" q=quarter page, l=single line, 1-9=# lines.\n");
294 error(" When asked for next file: confirm=yes, n=skip to next\n");
295 error(" s=stop (exit), h,q,l,1-9=yes with that # lines.\n");
296 exit(exitcode);
297 }
298
299
300 EXPORT int
301 main(ac, av)
302 int ac;
303 char *av[];
304 {
305 int i;
306 int cac;
307 char *const *cav;
308 int fac;
309 char **fav;
310
311 save_args(ac, av);
312
313 (void) setlocale(LC_ALL, "");
314
315 #ifdef USE_NLS
316 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
317 #define TEXT_DOMAIN "p" /* Use this only if it weren't */
318 #endif
319 { char *dir;
320 dir = searchfileinpath("share/locale", F_OK,
321 SIP_ANY_FILE|SIP_NO_PATH, NULL);
322 if (dir)
323 (void) bindtextdomain(TEXT_DOMAIN, dir);
324 else
325 #if defined(PROTOTYPES) && defined(INS_BASE)
326 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
327 #else
328 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
329 #endif
330 (void) textdomain(TEXT_DOMAIN);
331 }
332 #endif /* USE_NLS */
333
334
335 cac = --ac;
336 cav = ++av;
337
338 if (getallargs(&cac, &cav, options, &help, &prvers, &debug, &nobeep,
339 &psize, &psize,
340 &lwidth, &lwidth,
341 &supressblank, &supressblank,
342 &clear, &clear,
343 &dosmode, &autodos,
344 &endline, &endline,
345 &raw, &raw,
346 &raw8,
347 &silent, &silent,
348 &tab, &tab,
349 &ununderline,
350 &visible, &visible) < 0) {
351 errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
352 usage(EX_BAD);
353 }
354 if (help) usage(0);
355 if (prvers) {
356 /* BEGIN CSTYLED */
357 gtprintf("p %s %s (%s-%s-%s)\n\n", "2.4", "2021/08/20", HOST_CPU, HOST_VENDOR, HOST_OS);
358 gtprintf("Copyright (C) 1985, 87-92, 95-99, 2000-2021 %s\n", _("Jörg Schilling"));
359 gtprintf("This is free software; see the source for copying conditions. There is NO\n");
360 gtprintf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
361 /* END CSTYLED */
362 exit(0);
363 }
364
365 shell = getenv("BEEP");
366 if (shell != NULL && streql(shell, "off"))
367 nobeep = TRUE;
368 if ((editor = getenv("EDITOR")) == NULL)
369 editor = "vi";
370 if ((shell = getenv("SHELL")) == NULL)
371 shell = "sh";
372
373 underline = !raw && !visible;
374
375 cac = ac;
376 cav = av;
377 for (i = 0; getfiles(&cac, &cav, options) > 0; i++, cac--, cav++);
378
379 if (0 /*fav = (char **)malloc(i*sizeof(char *))*/) {
380 cac = ac;
381 cav = av;
382 fac = i;
383 for (i = 0; getfiles(&cac, &cav, options) > 0;
384 i++, cac--, cav++) {
385 fav[i] = *cav;
386 }
387 } else {
388 cac = ac;
389 cav = av;
390 getfiles(&cac, &cav, options);
391 }
392
393 if (cac == 0 && isatty(fdown(stdin)))
394 usage(EX_BAD);
395
396 if (get_modes() < 0) {
397 silent++;
398 if (!ununderline)
399 underline = FALSE;
400 }
401
402
403 /* if (underline || !silent)*/
404 init_termcap();
405 init_tty_size();
406
407 if (!silent) {
408 usleep(150000); /* XXX Hack bis Jobcontrol im bsh geht !!! */
409 set_modes();
410 }
411
412 init_charset();
413
414 #ifdef BUFSIZ /* XXX #ifdef HAVE_SETBUF ??? */
415 setbuf(stdout, buffer);
416 #endif
417
418 /*
419 * If we evaluate "has_termcap" here, we could avoid to reduce the width
420 * of the terminal in case that "am" but not "xn" is present. This
421 * however would result in missing line breaks in files created by the
422 * screen(1) utility.
423 */
424 if (am && !xn && lwidth > 2)
425 lwidth--;
426 lines = psize-2;
427
428 fac = cac;
429 #ifdef DEBUG
430 printf("%d\n", cac);
431 for (i = 0; i < cac; i++)
432 printf("%s\n", cav[i]);
433 #endif
434
435 if (cac == 0) {
436 filename = "";
437 linecnt = 0;
438 f = stdin;
439 page();
440 } else {
441 if (cac > 1)
442 nameprint++;
443 for (;;) {
444 if ((f = fileopen(*cav, "r")) == (FILE *) NULL) {
445 errmsg("Can not open '%s'.\n", *cav);
446 } else {
447 filename = *cav;
448 if (nameprint) {
449 printf("%s\n%s\n%s\n",
450 dcl, filename, dcl);
451 linecnt = 3;
452 } else
453 linecnt = 0;
454 page();
455 fclose(f);
456 f = (FILE *)0;
457 }
458 for (i = 0; ; ) {
459 if (direction == FORWARD) {
460 cac--, cav++;
461 if (cac <= 0)
462 reset_modes(), exit(0);
463 } else {
464 if (cac < fac) {
465 cac++, cav--;
466 }
467 }
468 if (silent) break;
469 if (i++ == 0) putchar('\n');
470 err:
471
472 start_standout();
473 gtprintf("NEXT FILE (%s)?", *cav);
474 end_standout();
475 fflush(stdout);
476 lines = psize-2;
477
478 switch (get_action()) {
479
480 case -1:
481 goto err;
482 case 1:
483 continue;
484 }
485 break;
486 }
487 clearline();
488 }
489 }
490 reset_modes();
491 exit(0);
492 return (0); /* Keep lint happy */
493 }
494
495 LOCAL void
496 page()
497 {
498 register int c;
499 register int cnt;
500 register unsigned char *s;
501 register unsigned char **rctab;
502 int ocolcnt = -1;
503
504 rctab = ctab;
505 ofpos = (off_t)0;
506 len = 0; /* fill_buf() on next nextc() */
507 file_raise(f, FALSE);
508 #ifdef __nonono__ /* FreeBSD would read single bytes */
509 setbuf(f, NULL);
510 #endif
511 lineno = 0;
512 colcnt = 0;
513
514 if (searchnext && do_search() < 0) {
515 if (!more())
516 return;
517 }
518
519 while ((c = nextc()) != EOF) {
520 if (c < 0) { /* -2 on error */
521 errmsg("Error reading '%s'.\n", filename);
522 return;
523 }
524 if (c == '_' && underline) { /* underlining */
525 if (peekc() != '\b') {
526 if (outchar('_'))
527 return;
528 continue;
529 }
530 getnextch(); /* it _is_ a ^H ! */
531 if (peekc() == '_')
532 goto bold;
533 underl++;
534
535 } else if (c == '+' && underline && peekc() == '\b') {
536 getnextch();
537 } else if (c == '\r' &&
538 (autodos || dosmode) && peekc() == '\n') {
539 /* EMPTY */
540 } else if (c == '\n') {
541 if (ocolcnt == 0 && colcnt == 0 && supressblank)
542 continue;
543 ocolcnt = colcnt;
544 lineno++;
545 if (endline) {
546 if (outchar('$'))
547 return;
548 }
549 if (outchar('\n'))
550 return;
551 } else if (c == '\t' && !tab) {
552 cnt = 8 - (colcnt&7);
553 while (--cnt >= 0)
554 if (outchar(' '))
555 return;
556 } else if (peekc() == '\b' && underline) {
557 getnextch(); /* ^H */
558 bold:
559 while (peekc() == c) {
560 getnextch();
561 if (peekc() == '\b')
562 getnextch();
563 else
564 break;
565 }
566 ungetch(c);
567 standout++;
568 } else {
569 if (raw || iswprint(c)) {
570 if (outchar(c))
571 return;
572 } else {
573 #if MB_LEN_MAX > 1
574 int i = clen;
575 while (--i >= 0) {
576 s = rctab[*cp++];
577 while (*s)
578 if (outchar(*s++))
579 return;
580 }
581 #else
582 s = rctab[c];
583 while (*s)
584 if (outchar(*s++))
585 return;
586 #endif
587 }
588 }
589 }
590 fflush(stdout);
591 }
592
593 LOCAL int
594 outchar(c)
595 int c;
596 {
597 #if MB_LEN_MAX > 1
598 unsigned char b[MB_LEN_MAX];
599 unsigned char *p = b;
600 int l;
601
602
603 l = wctomb((char *)b, c);
604 if (l < 0) {
605 l = 1;
606 b[0] = '?';
607 }
608 #endif
609
610 if (c == '\n') {
611 if (len <= lwidth)
612 fflush(stdout);
613 if (++linecnt >= lines) {
614 if (!more())
615 return (1);
616 clearline();
617 linecnt = 0;
618 } else {
619 putc('\n', stdout);
620 }
621 colcnt = 0;
622 return (0);
623 } else {
624 int w = wcwidth(c);
625
626 if (w < 0)
627 w = 1;
628 colcnt += w;
629 if (colcnt > lwidth) {
630 if (outchar('\n'))
631 return (1);
632 colcnt = 1;
633 }
634 if (standout) {
635 standout--;
636 if (underl) {
637 underl--;
638 start_ul();
639 start_xstandout();
640 #if MB_LEN_MAX > 1
641 while (--l >= 0)
642 putc(*p++, stdout);
643 #else
644 putc(c, stdout);
645 #endif
646 end_xstandout();
647 end_ul();
648 } else {
649 start_xstandout();
650 #if MB_LEN_MAX > 1
651 while (--l >= 0)
652 putc(*p++, stdout);
653 #else
654 putc(c, stdout);
655 #endif
656 end_xstandout();
657 }
658 } else if (underl) {
659 underl--;
660 start_ul();
661 #if MB_LEN_MAX > 1
662 while (--l >= 0)
663 putc(*p++, stdout);
664 #else
665 putc(c, stdout);
666 #endif
667 end_ul();
668 } else {
669 #if MB_LEN_MAX > 1
670 while (--l >= 0)
671 putc(*p++, stdout);
672 #else
673 putc(c, stdout);
674 #endif
675 }
676 return (0);
677 }
678 }
679
680 LOCAL void
681 moreprompt()
682 {
683 float percent;
684 off_t size = -1;
685 off_t pos = -1;
686
687 lines = psize-2;
688 if (f) {
689 size = filesize(f);
690 pos = filepos(f) - len;
691 }
692 start_standout();
693 if (!*filename || !f || size < 0 || pos < 0)
694 gtprintf("%s%c MORE?",
695 filename,
696 *filename ? ':' : '-');
697 else {
698 percent = (float)pos;
699 percent /= (float)size;
700 percent *= 100.0;
701 gtprintf("%s%c %.1f %% MORE?",
702 filename,
703 *filename ? ':' : '-',
704 percent);
705 }
706 end_standout();
707 fflush(stdout);
708 }
709
710 LOCAL BOOL
711 more()
712 {
713 if (silent)
714 return (TRUE);
715 putchar('\n');
716 for (;;) {
717 moreprompt();
718 switch (get_action()) {
719
720 case 1:
721 return (FALSE);
722 case -1:
723 continue;
724 }
725 ofpos = filepos(f)-len;
726 break;
727 }
728 return (TRUE);
729 }
730
731
732 /*
733 * Return:
734 * -1 error
735 * 0 continue this file
736 * 1 stop on this file
737 * EXIT:
738 * on demand
739 */
740 LOCAL int
741 get_action()
742 {
743 int c;
744 char buf[128];
745
746 direction = FORWARD;
747 searchnext = 0;
748
749 switch (c = inwchar()) {
750
751 case 'p':
752 case 'P':
753 case 'n':
754 case 'N':
755 direction = (c == 'P' || c == 'p');
756 clearline();
757 return (1);
758 case 's':
759 case 'S':
760 case 003 : /* ^C */
761 case 004 : /* ^D */
762 case 034 : /* ^\ */
763 case 0177: /* DEL */
764 case EOF :
765 fixtty(0);
766 /* NOTREACHED */
767 case 'Y':
768 case 'y':
769 case '\r':
770 case '\n':
771 case ' ':
772 if (clear)
773 clearscreen();
774 break;
775 case 'H':
776 case 'h':
777 lines = lines/2;
778 break;
779 case 'Q':
780 case 'q':
781 lines = lines/4;
782 break;
783 case 'L':
784 case 'l':
785 lines = 1;
786 break;
787 case '1':
788 case '2':
789 case '3':
790 case '4':
791 case '5':
792 case '6':
793 case '7':
794 case '8':
795 case '9':
796 lines = c-'0';
797 break;
798 case '/':
799 clearline();
800 printf("/");
801 fflush(stdout);
802 if (!read_pattern())
803 return (-1);
804 /* FALLTHRU */
805 case 'r':
806 case 'R':
807 if (f == (FILE *)0)
808 searchnext = 1;
809 else if (do_search() < 0)
810 return (-1);
811 break;
812 case '\f':
813 redraw(); /* XXX eigentlich nicht ?? */
814 break;
815 case '?':
816 clearline();
817 onlinehelp();
818 return (-1);
819 case '!':
820 clearline();
821 sprintf(buf, "%s -t", shell);
822 (void) system(buf);
823 return (-1);
824 case 'v':
825 case 'V':
826 if (f != stdin) {
827 clearline();
828 sprintf(buf, "%s +%d %s", editor, lineno, filename);
829 printf("%s", buf);
830 fflush(stdout);
831 (void) system(buf);
832 return (-1);
833 }
834 /* FALLTHRU */
835 default:
836 if (!nobeep)
837 putchar('\007');
838 clearline();
839 return (-1);
840 }
841 return (0);
842 }
843
844 LOCAL void
845 onlinehelp()
846 {
847 /* BEGIN CSTYLED */
848 gtprintf("\n---------------------------------------------------------------\n");
849 gtprintf("N, n Next File\n");
850 gtprintf("P, p Previous File\n");
851 gtprintf("S, s, ^C, ^D, ^\\, DEL Exit (stop)\n");
852 gtprintf("Y, y, <return>, <space> Display next screenfull of text\n");
853 gtprintf("H, h Display next half screenfull of text\n");
854 gtprintf("Q, q Display next quarter screenfull of text\n");
855 gtprintf("L, l Display next line of text\n");
856 gtprintf("1-9 Display next <n> lines of text\n");
857 gtprintf("/pattern Search for <pattern>\n");
858 gtprintf("R, r Re-search for <pattern>\n");
859 gtprintf("^L Redraw screen\n");
860 gtprintf("? Display this message\n");
861 gtprintf("! Execute command\n");
862 gtprintf("V, v Edit file\n");
863 gtprintf("---------------------------------------------------------------\n");
864 /* END CSTYLED */
865 }
866
867 LOCAL void
868 redraw()
869 {
870 if (f && fileseek(f, ofpos) < 0) {
871 if (!nobeep)
872 putchar('\007');
873 clearline();
874 return;
875 }
876 len = 0;
877 clearscreen();
878 }
879
880 LOCAL int
881 inchar()
882 {
883 char c;
884 int ret = 0;
885
886 c = '\004'; /* return ^D on EOF */
887 do {
888 # ifdef USE_GETCH
889 c = getch(); /* DOS console input */
890 # else
891 ret = read(tty, &c, 1);
892 # endif
893 } while (ret < 0 && geterrno() == EINTR);
894 if (ret == 0)
895 return (EOF);
896 return (c);
897 }
898
899 #if MB_LEN_MAX > 1
900 /*
901 * Get next wide character from tty
902 */
903 LOCAL int
904 inwchar()
905 {
906 register int cur_max = MB_CUR_MAX;
907 register int i;
908 int mlen;
909 wchar_t c = -1;
910 char cstr[MB_LEN_MAX];
911 char *csp;
912 int ic;
913
914 (void) mbtowc(NULL, NULL, 0);
915 for (i = 1, csp = cstr; i <= cur_max; i++) {
916 ic = inchar();
917 if (ic == EOF)
918 break;
919 *csp++ = (char)ic;
920 mlen = mbtowc(&c, cstr, i);
921 if (mlen >= 0)
922 break;
923 (void) mbtowc(NULL, NULL, 0);
924 }
925 #ifdef _NEXTWC_DEBUG
926 fprintf(stderr, "C %d %x\n", c, c);
927 #endif
928 return ((int)c);
929 }
930 #endif
931
932
933 #ifndef nextc
934 LOCAL int
935 nextc()
936 {
937 if (--len >= 0) {
938 return ((int) *bp++);
939 } else {
940 if (fill_buf() <= 0)
941 return (len == 0 ? EOF : -2);
942 }
943 len--;
944 return ((int) *bp++);
945 }
946 #endif
947
948 #if MB_LEN_MAX > 1
949 /*
950 * Read the next multi byte character from the buffer.
951 * If the buffer is empty or if less than a multi byte character is inside,
952 * it is refilled. When an illegal byte sequence is discovered, a single
953 * byte is removed from the buffer in hope to be able to resync.
954 */
955 LOCAL int
956 nextwc()
957 {
958 BOOL eof = FALSE;
959 int mlen;
960 wchar_t c;
961
962 if (len <= 0) {
963 int olen;
964 again:
965 olen = len;
966 if (fill_buf() <= 0) {
967 return (len == 0 ? EOF : -2);
968 } else if (len > 0 && olen == len) {
969 eof = TRUE;
970 }
971 }
972 mlen = mbtowc(&c, (char *)bp, len);
973 if (mlen >= 0) {
974 if (mlen == 0)
975 mlen = 1;
976 clen = mlen;
977 cp = bp;
978 bp += mlen;
979 len -= mlen;
980 return (c);
981 } else {
982 mbtowc(NULL, NULL, 0);
983 if (len < MB_CUR_MAX && !eof) {
984 seterrno(0);
985 goto again;
986 }
987 clen = 1;
988 cp = bp;
989 bp++;
990 len--;
991 #ifdef EILSEQ
992 if (geterrno() == EILSEQ) {
993 return (*cp);
994 }
995 #endif
996 }
997 return (-2);
998 }
999
1000 /*
1001 * The same as nextwc(), but the buffer is untouched.
1002 */
1003 LOCAL int
1004 peekwc()
1005 {
1006 BOOL eof = FALSE;
1007 int mlen;
1008 wchar_t c;
1009
1010 if (len <= 0) {
1011 int olen;
1012 again:
1013 olen = len;
1014 if (fill_buf() <= 0) {
1015 return (len == 0 ? EOF : -2);
1016 } else if (len > 0 && olen == len) {
1017 eof = TRUE;
1018 }
1019 }
1020 mlen = mbtowc(&c, (char *)bp, len);
1021 if (mlen >= 0) {
1022 if (mlen == 0)
1023 mlen = 1;
1024 pclen = mlen;
1025 pcp = bp;
1026 return (c);
1027 } else {
1028 mbtowc(NULL, NULL, 0);
1029 if (len < MB_CUR_MAX && !eof) {
1030 seterrno(0);
1031 goto again;
1032 }
1033 pclen = 1;
1034 pcp = bp;
1035 #ifdef EILSEQ
1036 if (geterrno() == EILSEQ) {
1037 return (*pcp);
1038 }
1039 #endif
1040 }
1041 return (-2);
1042 }
1043 #endif
1044
1045 #ifndef ungetch
1046 LOCAL int
1047 ungetch(c)
1048 int c;
1049 {
1050 if (c == EOF)
1051 return (c);
1052 /*
1053 * If bp is at the beginning of the buffer, this may go
1054 * to one character before the buffer (see below).
1055 */
1056 len++;
1057 return (*--bp = c);
1058 }
1059 #endif
1060
1061 #if MB_LEN_MAX > 1
1062 /*
1063 * Return the character back to the buffer.
1064 */
1065 LOCAL int
1066 ungetwch(c)
1067 int c;
1068 {
1069 unsigned char b[MB_LEN_MAX];
1070 unsigned char *p;
1071 int l;
1072
1073 if (c == EOF)
1074 return (c);
1075
1076 l = wctomb((char *)b, c);
1077 if (l < 0) {
1078 l = 1;
1079 b[0] = '?';
1080 }
1081 len += l;
1082 p = &b[l];
1083 while (--l >= 0)
1084 *--bp = *--p;
1085
1086 return (c);
1087 }
1088
1089 /*
1090 * Consume the last character fetched by peekwc()
1091 */
1092 LOCAL void
1093 getnextwch()
1094 {
1095 len -= pclen;
1096 bp += pclen;
1097 cp = pcp;
1098 pclen = 0;
1099 }
1100 #endif
1101
1102 LOCAL int
1103 fill_buf()
1104 {
1105 int i;
1106
1107 /*
1108 * Allow ungetch() to always put back one character.
1109 * This is done by reserving one char before the normal
1110 * space in "mybuf".
1111 */
1112
1113 if (len > 0) {
1114 unsigned char *p = bp;
1115
1116 /*
1117 * Move a partial character left at the end of the buffer
1118 * to the space before the beginning of the buffer.
1119 */
1120 if (len > MB_LEN_MAX)
1121 len = MB_LEN_MAX;
1122 p = &mybuf[(2*MB_LEN_MAX) - len];
1123 for (i = len; --i >= 0; ) {
1124 *p++ = *bp++;
1125 }
1126 bp = &mybuf[(2*MB_LEN_MAX) - len];
1127 } else {
1128 len = 0;
1129 bp = &mybuf[(2*MB_LEN_MAX)];
1130 }
1131 i = fileread(f, &mybuf[2*MB_LEN_MAX], sizeof (mybuf) - 2*MB_LEN_MAX);
1132 if (i < 0)
1133 return (i);
1134 return (len += i);
1135 }
1136
1137 LOCAL BOOL
1138 read_pattern()
1139 {
1140 int patlen;
1141 register int c;
1142 register int count = 0;
1143 #if MB_LEN_MAX > 1
1144 register wchar_t *s = searchbuf;
1145 unsigned char b[MB_LEN_MAX];
1146 #else
1147 register char *s = searchbuf;
1148 #endif
1149 register unsigned char *p;
1150 register int i;
1151
1152 while ((c = inwchar()) != EOF &&
1153 count++ < (SEARCHSIZE - 1) &&
1154 c != '\004' && c != '\r' && c != '\n') {
1155
1156 if (c == 0177) { /* DEL */
1157 if (s == searchbuf) {
1158 if (!nobeep)
1159 putchar('\007');
1160 } else {
1161 --count;
1162 --s;
1163 #if MB_LEN_MAX > 1 && defined(HAVE_WCWIDTH)
1164 if (iswprint(*s))
1165 i = wcwidth(*s);
1166 else
1167 i = csize[*s & 0xFF];
1168 #else
1169 i = csize[*s & 0xFF];
1170 #endif
1171 for (; --i >= 0; )
1172 printf("\b \b");
1173 }
1174 fflush(stdout);
1175 } else {
1176 #if MB_LEN_MAX > 1 && defined(HAVE_WCWIDTH)
1177 int l;
1178
1179 if (iswprint(c)) {
1180 l = wctomb((char *)b, c);
1181 if (l < 1) {
1182 p = ctab[c & 0xFF];
1183 } else {
1184 p = b;
1185 b[l] = '\0';
1186 }
1187 } else {
1188 p = ctab[c & 0xFF];
1189 }
1190 #else
1191 p = ctab[c & 0xFF];
1192 #endif
1193 *s++ = c;
1194 while (*p)
1195 putchar(*p++);
1196 fflush(stdout);
1197 }
1198 }
1199 *s = '\0';
1200 if (aux)
1201 free((char *)aux);
1202 #if MB_LEN_MAX > 1
1203 patlen = wcslen(searchbuf);
1204 #else
1205 patlen = strlen(searchbuf);
1206 #endif
1207 aux = (int *) malloc(patlen * sizeof (int));
1208 state = (int *) malloc((patlen+1) * sizeof (int));
1209 #if MB_LEN_MAX > 1
1210 alt = patwcompile(searchbuf, patlen, aux);
1211 #else
1212 alt = patcompile((unsigned char *)searchbuf, patlen, aux);
1213 #endif
1214 if (!alt) {
1215 gtprintf("Bad Pattern.\r");
1216 fflush(stdout);
1217 sleep(1);
1218 return (FALSE);
1219 }
1220 return (TRUE);
1221 }
1222
1223 LOCAL int
1224 do_search()
1225 {
1226 register unsigned char *lp;
1227 register unsigned char *rbp;
1228 unsigned char *sp;
1229 register int rest = len;
1230 off_t curpos;
1231 BOOL skipping = FALSE;
1232 int newlines = 0;
1233 unsigned char sbuf[P_BUFSIZE];
1234
1235 if (!alt) {
1236 if (!nobeep)
1237 putchar('\007');
1238 gtprintf("No previous search.\r");
1239 fflush(stdout);
1240 #ifdef DEBUG
1241 sleep(1);
1242 #endif
1243 return (-1);
1244 }
1245 curpos = filepos(f)-len;
1246
1247 #ifdef DEBUG
1248 fprintf(stderr,
1249 "Efilepos: %lld len: %d bp: 0x%X\n",
1250 (Llong)filepos(f), len, bp);
1251 #endif
1252 for (;;) {
1253 if (rest < MB_LEN_MAX) {
1254 int olen;
1255 /*
1256 * We may be operating on a copy and thus
1257 * need to set "len" to the remaining characters to
1258 * tell fill_buf() that it needs to do a refill.
1259 */
1260 olen = len = rest;
1261 if (fill_buf() <= 0 || olen == len) {
1262 if (!nobeep)
1263 putchar('\007');
1264 gtprintf("Pattern not found.\r");
1265 fflush(stdout);
1266 if (f && fileseek(f, curpos) >= 0)
1267 len = 0;
1268 return (-1);
1269 }
1270 newlines = 0;
1271 }
1272 rbp = lp = sp = bp;
1273 rest = len;
1274 if (underline &&
1275 findbytes(lp, rest, '\b') != NULL) {
1276 rest = unul(sbuf, rbp, len);
1277 rbp = lp = sp = sbuf;
1278 }
1279 for (; rest > 0; rest--) {
1280 #if MB_LEN_MAX > 1
1281 if (patmbmatch(searchbuf,
1282 #else
1283 if (patmatch((unsigned char *)searchbuf,
1284 #endif
1285 aux, rbp, 0, rest, alt, state)) {
1286 #ifdef DEBUG
1287 fprintf(stderr,
1288 "Afilepos: %lld rest: %d rbp: 0x%X lp: 0x%X\n",
1289 (Llong)filepos(f), rest, rbp, lp);
1290 #endif
1291 if (skipping) {
1292 printf("\n");
1293 if (sp == bp) {
1294 bp = lp;
1295 len = rest + (rbp - lp);
1296 } else {
1297 lp = bp;
1298 rbp = &bp[len];
1299 while (--newlines >= 0) {
1300 unsigned char *olp = lp;
1301 if ((lp = (Uchar *)
1302 findbytes(lp,
1303 rbp - lp,
1304 '\n')) ==
1305 NULL) {
1306 lp = olp;
1307 break;
1308 }
1309 lp++;
1310 }
1311 bp = lp;
1312 len = rbp - lp;
1313 }
1314 }
1315 #ifdef DEBUG
1316 fprintf(stderr,
1317 "Afilepos: %lld len: %d bp: 0x%X\n",
1318 (Llong)filepos(f), len, bp);
1319 #endif
1320 return (0);
1321 }
1322 if (*rbp++ == '\n') {
1323 /*
1324 * Remember last line start pointer.
1325 */
1326 lp = rbp;
1327 newlines++;
1328 if (!skipping) {
1329 skipping = TRUE;
1330 gtprintf("skipping...\r");
1331 fflush(stdout);
1332 }
1333 #ifdef DEBUG
1334 fprintf(stderr, ".");
1335 #endif
1336 }
1337 }
1338 }
1339 }
1340
1341 /*
1342 * Remove underlining and overstriking sequences.
1343 * Put the result into "ob".
1344 */
1345 LOCAL int
1346 unul(ob, ib, amt)
1347 register Uchar *ob;
1348 register Uchar *ib;
1349 register int amt;
1350 {
1351 register Uchar *oob = ob;
1352 wchar_t c;
1353 register ssize_t wclen;
1354
1355 mbtowc(NULL, NULL, 0);
1356 while (amt > 0) {
1357 wclen = mbtowc(&c, (char *)ib, amt);
1358 if (wclen < 1) {
1359 *ob++ = *ib++;
1360 amt--;
1361 continue;
1362 }
1363 amt -= wclen;
1364 ib += wclen;
1365 if (c == '_') { /* underlining */
1366 if (ib[0] != '\b') {
1367 ib -= wclen;
1368 while (--wclen >= 0)
1369 *ob++ = *ib++;
1370 continue;
1371 }
1372 ib++; /* eat ^H */
1373 amt--;
1374 wclen = mbtowc(&c, (char *)ib, amt);
1375 if (wclen > 0 && c == '_') { /* _ ^H _ */
1376 goto bold;
1377 }
1378 } else if (c == '+' && ib[0] == '\b') { /* overstriking */
1379 /* + ^H o */
1380
1381 ib++; /* eat ^H */
1382 amt--;
1383 } else if (ib[0] == '\b') {
1384 wchar_t c2;
1385 ssize_t wclen2;
1386 Uchar *oib;
1387
1388 /* N ^H N ^H N ^H N */
1389 ib++; /* eat ^H */
1390 amt--;
1391 bold:
1392 oib = ib - (wclen +1);
1393 while (amt > 0) {
1394 wclen2 = mbtowc(&c2, (char *)ib, amt);
1395 if (wclen2 < 1)
1396 break;
1397 if (c2 != c)
1398 break;
1399 ib += wclen2; /* eat c2 */
1400 amt -= wclen2;
1401 if (ib[0] == '\b') { /* Check for ^H */
1402 ib++; /* eat ^H */
1403 amt--;
1404 } else
1405 break;
1406 }
1407 while (--wclen >= 0)
1408 *ob++ = *oib++;
1409 } else {
1410 ib -= wclen;
1411 while (--wclen >= 0)
1412 *ob++ = *ib++;
1413 }
1414 }
1415 *ob = '\0';
1416 return (ob - oob);
1417 }
1418
1419 char stbuf[1024]; /* Bufer for termcap array (i.e. so and se) */
1420
1421 LOCAL void
1422 init_termcap()
1423 {
1424 char *tname;
1425 char *sbp;
1426
1427 sbp = stbuf;
1428
1429 if ((tname = getenv("TERM")) && tgetent(NULL, tname) == 1) {
1430 has_termcap = TRUE;
1431
1432 so = tgetstr("so", &sbp); /* start standout */
1433 se = tgetstr("se", &sbp); /* end standout */
1434 us = tgetstr("us", &sbp); /* start underline */
1435 ue = tgetstr("ue", &sbp); /* end underline */
1436 md = tgetstr("md", &sbp); /* start bold */
1437 me = tgetstr("me", &sbp); /* end attributes */
1438 ce = tgetstr("ce", &sbp); /* clear endline */
1439 cl = tgetstr("cl", &sbp); /* clear screen */
1440 li = tgetnum("li"); /* lines on screen */
1441 co = tgetnum("co"); /* columns on screen */
1442 am = tgetflag("am"); /* automatic margins */
1443 xn = tgetflag("xn"); /* newline ignored > 80 */
1444 if (so != NULL && se != NULL) {
1445 has_standout = TRUE;
1446 } else {
1447 so = se = NULL;
1448 }
1449 if (md != NULL && me != NULL) {
1450 has_bold = TRUE;
1451 } else {
1452 md = NULL;
1453 }
1454 if (us != NULL && ue != NULL) {
1455 has_ul = TRUE;
1456 } else {
1457 us = ue = NULL;
1458 }
1459 if (has_bold) {
1460 xso = md;
1461 xse = me;
1462 } else if (has_standout) {
1463 xso = so;
1464 xse = se;
1465 } else {
1466 xso = xse = NULL;
1467 }
1468 if (debug) {
1469 printf("so: %d bo: %d ul: %d\n",
1470 has_standout, has_bold, has_ul);
1471 sleep(1);
1472 }
1473 }
1474 }
1475
1476 LOCAL int
1477 oc(c)
1478 int c;
1479 {
1480 return (putchar(c));
1481 }
1482
1483 LOCAL void
1484 start_standout()
1485 {
1486 tputs(so, 1, oc);
1487 }
1488
1489 LOCAL void
1490 end_standout()
1491 {
1492 tputs(se, 1, oc);
1493 }
1494
1495 #ifdef __needed__
1496 LOCAL void
1497 start_bold()
1498 {
1499 tputs(md, 1, oc);
1500 }
1501 #endif
1502
1503 LOCAL void
1504 end_attr()
1505 {
1506 tputs(me, 1, oc);
1507 }
1508
1509 LOCAL void
1510 start_xstandout()
1511 {
1512 tputs(xso, 1, oc);
1513 }
1514
1515 LOCAL void
1516 end_xstandout()
1517 {
1518 tputs(xse, 1, oc);
1519 }
1520
1521 LOCAL void
1522 start_ul()
1523 {
1524 if (has_ul)
1525 tputs(us, 1, oc);
1526 }
1527
1528 LOCAL void
1529 end_ul()
1530 {
1531 if (has_ul)
1532 tputs(ue, 1, oc);
1533 }
1534
1535 LOCAL void
1536 clearline()
1537 {
1538 int i;
1539
1540 if (silent) {
1541 putchar('\n');
1542 return;
1543 }
1544 putchar('\r');
1545 if (ce) {
1546 tputs(ce, 1, oc);
1547 } else {
1548 for (i = 1; i < lwidth; i++)
1549 putchar(' ');
1550 putchar('\r');
1551 }
1552 fflush(stdout);
1553 }
1554
1555 LOCAL void
1556 clearscreen()
1557 {
1558 if (cl)
1559 tputs(cl, 1, oc);
1560 }
1561
1562 LOCAL void
1563 init_tty_size()
1564 {
1565 #ifdef no_TIOCGSIZE
1566 #if defined(TIOCGSIZE) || defined(TIOCGWINSZ)
1567 #ifdef TIOCGWINSZ
1568 struct winsize ws;
1569
1570 ws.ws_rows = 0;
1571 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) >= 0) {
1572 if (ws.ws_rows) {
1573 psize = ws.ws_rows;
1574 lwidth = ws.ws_cols;
1575 }
1576 }
1577 #else
1578 struct ttysize ts;
1579
1580 ts.ts_lines = 0;
1581 if (ioctl(STDOUT_FILENO, TIOCGSIZE, (char *)&ts) >= 0) {
1582 if (ts.ts_lines) {
1583 psize = ts.ts_lines;
1584 lwidth = ts.ts_cols;
1585 }
1586 }
1587 #endif
1588 #endif
1589 #else
1590 if (psize == 0) {
1591 if (li > 0 && li < 1000)
1592 psize = li;
1593 else
1594 psize = DEF_PSIZE;
1595 }
1596 if (lwidth == 0) {
1597 if (co > 0 && co < 1000)
1598 lwidth = co;
1599 else
1600 lwidth = DEF_LWIDTH;
1601 }
1602 #endif
1603 }
1604
1605 LOCAL int
1606 get_modes()
1607 {
1608 # ifdef USE_V7_TTY
1609 return (ioctl(STDOUT_FILENO, TIOCGETP, &old));
1610
1611 # else /* USE_V7_TTY */
1612
1613 # ifdef USE_TERMIOS
1614 # ifdef TCSANOW
1615 return (tcgetattr(STDOUT_FILENO, &old));
1616 # else
1617 return (ioctl(STDOUT_FILENO, TCGETS, &old));
1618 # endif
1619 # else /* USE_TERMIOS */
1620 return (0);
1621 # endif /* USE_TERMIOS */
1622 # endif /* USE_V7_TTY */
1623 }
1624
1625 LOCAL void
1626 set_modes()
1627 {
1628 #ifdef HAVE__DEV_TTY
1629 if (tty < 0 && (tty = open("/dev/tty", O_RDONLY)) < 0)
1630 errmsg("Can't open '/dev/tty'\n");
1631 #endif
1632 if (tty < 0)
1633 tty = fileno(stderr);
1634
1635 /*
1636 * Do signal handling only if they are not already
1637 * ignored.
1638 */
1639 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
1640 signal(SIGINT, fixtty);
1641 #ifdef SIGQUIT
1642 signal(SIGQUIT, fixtty);
1643 #endif
1644 #ifdef SIGTSTP
1645 if (signal(SIGTSTP, SIG_IGN) == SIG_DFL)
1646 signal(SIGTSTP, tstp);
1647 #endif
1648 }
1649 # ifdef USE_V7_TTY
1650 movebytes(&old, &new, sizeof (old));
1651 # ifdef LPASS8
1652 {
1653 int lmode;
1654
1655 ioctl(STDOUT_FILENO, TIOCLGET, &lmode);
1656 if (lmode & LPASS8)
1657 raw8 = TRUE;
1658 }
1659 # else
1660 if (old.sg_flags & RAW)
1661 raw8 = TRUE;
1662 # endif
1663 new.sg_flags |= CBREAK;
1664 new.sg_flags &= ~ECHO;
1665 if (ioctl(STDOUT_FILENO, TIOCSETN, &new) < 0)
1666 comerr("Can not set new modes.\n");
1667
1668 # else /* USE_V7_TTY */
1669
1670 # ifdef USE_TERMIOS
1671 movebytes(&old, &new, sizeof (old));
1672 if (!(old.c_iflag & ISTRIP))
1673 raw8 = TRUE;
1674 #ifdef __never__
1675 new.c_iflag = ICRNL;
1676 new.c_oflag = (OPOST|ONLCR);
1677 new.c_lflag = ISIG;
1678 #endif
1679 new.c_lflag &= ~(ICANON|ECHO);
1680 new.c_cc[VMIN] = 1;
1681 new.c_cc[VTIME] = 0;
1682 # ifdef TCSANOW
1683 if (tcsetattr(STDOUT_FILENO, TCSADRAIN, &new) < 0)
1684 # else
1685 if (ioctl(STDOUT_FILENO, TCSETSW, &new) < 0)
1686 # endif
1687 comerr("Can not set new modes.\n");
1688 # endif /* USE_TERMIOS */
1689
1690 # endif /* USE_V7_TTY */
1691
1692 #ifdef CATCH_SIGCONT_here
1693 #ifdef SIGCONT
1694 signal(SIGONT, redraw); /* XXX ??? */
1695 #endif
1696 #endif
1697 }
1698
1699 /*
1700 * Reset to previous tty modes.
1701 */
1702 LOCAL void
1703 reset_modes()
1704 {
1705 if (!silent) {
1706 # ifdef USE_V7_TTY
1707 if (ioctl(STDOUT_FILENO, TIOCSETN, &old) < 0)
1708
1709 # else /* USE_V7_TTY */
1710
1711 # ifdef USE_TERMIOS
1712 # ifdef TCSANOW
1713 if (tcsetattr(STDOUT_FILENO, TCSADRAIN, &old) < 0)
1714 # else
1715 if (ioctl(STDOUT_FILENO, TCSETSW, &old) < 0)
1716 # endif
1717 # else /* USE_TERMIOS */
1718 if (0)
1719 # endif /* USE_TERMIOS */
1720 # endif /* USE_V7_TTY */
1721 comerr("Can not reset old modes.\n");
1722 }
1723 }
1724
1725 /*
1726 * Fix tty and exit.
1727 */
1728 LOCAL void
1729 fixtty(sig)
1730 int sig;
1731 {
1732 end_standout();
1733 end_attr();
1734 end_ul();
1735 clearline();
1736 reset_modes();
1737 exit(0);
1738 }