"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "less-424/screen.c" of archive less-424.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /*
2 * Copyright (C) 1984-2008 Mark Nudelman
3 *
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
6 *
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
9 */
10
11
12 /*
13 * Routines which deal with the characteristics of the terminal.
14 * Uses termcap to be as terminal-independent as possible.
15 */
16
17 #include "less.h"
18 #include "cmd.h"
19
20 #if MSDOS_COMPILER
21 #include "pckeys.h"
22 #if MSDOS_COMPILER==MSOFTC
23 #include <graph.h>
24 #else
25 #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
26 #include <conio.h>
27 #if MSDOS_COMPILER==DJGPPC
28 #include <pc.h>
29 extern int fd0;
30 #endif
31 #else
32 #if MSDOS_COMPILER==WIN32C
33 #include <windows.h>
34 #endif
35 #endif
36 #endif
37 #include <time.h>
38
39 #else
40
41 #if HAVE_SYS_IOCTL_H
42 #include <sys/ioctl.h>
43 #endif
44
45 #if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS
46 #include <termios.h>
47 #else
48 #if HAVE_TERMIO_H
49 #include <termio.h>
50 #else
51 #if HAVE_SGSTAT_H
52 #include <sgstat.h>
53 #else
54 #include <sgtty.h>
55 #endif
56 #endif
57 #endif
58
59 #if HAVE_TERMCAP_H
60 #include <termcap.h>
61 #endif
62 #ifdef _OSK
63 #include <signal.h>
64 #endif
65 #if OS2
66 #include <sys/signal.h>
67 #include "pckeys.h"
68 #endif
69 #if HAVE_SYS_STREAM_H
70 #include <sys/stream.h>
71 #endif
72 #if HAVE_SYS_PTEM_H
73 #include <sys/ptem.h>
74 #endif
75
76 #endif /* MSDOS_COMPILER */
77
78 /*
79 * Check for broken termios package that forces you to manually
80 * set the line discipline.
81 */
82 #ifdef __ultrix__
83 #define MUST_SET_LINE_DISCIPLINE 1
84 #else
85 #define MUST_SET_LINE_DISCIPLINE 0
86 #endif
87
88 #if OS2
89 #define DEFAULT_TERM "ansi"
90 static char *windowid;
91 #else
92 #define DEFAULT_TERM "unknown"
93 #endif
94
95 #if MSDOS_COMPILER==MSOFTC
96 static int videopages;
97 static long msec_loops;
98 static int flash_created = 0;
99 #define SETCOLORS(fg,bg) { _settextcolor(fg); _setbkcolor(bg); }
100 #endif
101
102 #if MSDOS_COMPILER==BORLANDC
103 static unsigned short *whitescreen;
104 static int flash_created = 0;
105 #endif
106 #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
107 #define _settextposition(y,x) gotoxy(x,y)
108 #define _clearscreen(m) clrscr()
109 #define _outtext(s) cputs(s)
110 #define SETCOLORS(fg,bg) { textcolor(fg); textbackground(bg); }
111 extern int sc_height;
112 #endif
113
114 #if MSDOS_COMPILER==WIN32C
115 struct keyRecord
116 {
117 int ascii;
118 int scan;
119 } currentKey;
120
121 static int keyCount = 0;
122 static WORD curr_attr;
123 static int pending_scancode = 0;
124 static WORD *whitescreen;
125
126 static HANDLE con_out_save = INVALID_HANDLE_VALUE; /* previous console */
127 static HANDLE con_out_ours = INVALID_HANDLE_VALUE; /* our own */
128 HANDLE con_out = INVALID_HANDLE_VALUE; /* current console */
129
130 extern int quitting;
131 static void win32_init_term();
132 static void win32_deinit_term();
133
134 #define FG_COLORS (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY)
135 #define BG_COLORS (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY)
136 #define MAKEATTR(fg,bg) ((WORD)((fg)|((bg)<<4)))
137 #define SETCOLORS(fg,bg) { curr_attr = MAKEATTR(fg,bg); \
138 if (SetConsoleTextAttribute(con_out, curr_attr) == 0) \
139 error("SETCOLORS failed"); }
140 #endif
141
142 #if MSDOS_COMPILER
143 public int nm_fg_color; /* Color of normal text */
144 public int nm_bg_color;
145 public int bo_fg_color; /* Color of bold text */
146 public int bo_bg_color;
147 public int ul_fg_color; /* Color of underlined text */
148 public int ul_bg_color;
149 public int so_fg_color; /* Color of standout text */
150 public int so_bg_color;
151 public int bl_fg_color; /* Color of blinking text */
152 public int bl_bg_color;
153 static int sy_fg_color; /* Color of system text (before less) */
154 static int sy_bg_color;
155
156 #else
157
158 /*
159 * Strings passed to tputs() to do various terminal functions.
160 */
161 static char
162 *sc_pad, /* Pad string */
163 *sc_home, /* Cursor home */
164 *sc_addline, /* Add line, scroll down following lines */
165 *sc_lower_left, /* Cursor to last line, first column */
166 *sc_return, /* Cursor to beginning of current line */
167 *sc_move, /* General cursor positioning */
168 *sc_clear, /* Clear screen */
169 *sc_eol_clear, /* Clear to end of line */
170 *sc_eos_clear, /* Clear to end of screen */
171 *sc_s_in, /* Enter standout (highlighted) mode */
172 *sc_s_out, /* Exit standout mode */
173 *sc_u_in, /* Enter underline mode */
174 *sc_u_out, /* Exit underline mode */
175 *sc_b_in, /* Enter bold mode */
176 *sc_b_out, /* Exit bold mode */
177 *sc_bl_in, /* Enter blink mode */
178 *sc_bl_out, /* Exit blink mode */
179 *sc_visual_bell, /* Visual bell (flash screen) sequence */
180 *sc_backspace, /* Backspace cursor */
181 *sc_s_keypad, /* Start keypad mode */
182 *sc_e_keypad, /* End keypad mode */
183 *sc_init, /* Startup terminal initialization */
184 *sc_deinit; /* Exit terminal de-initialization */
185 #endif
186
187 static int init_done = 0;
188
189 public int auto_wrap; /* Terminal does \r\n when write past margin */
190 public int ignaw; /* Terminal ignores \n immediately after wrap */
191 public int erase_char; /* The user's erase char */
192 public int erase2_char; /* The user's other erase char */
193 public int kill_char; /* The user's line-kill char */
194 public int werase_char; /* The user's word-erase char */
195 public int sc_width, sc_height; /* Height & width of screen */
196 public int bo_s_width, bo_e_width; /* Printing width of boldface seq */
197 public int ul_s_width, ul_e_width; /* Printing width of underline seq */
198 public int so_s_width, so_e_width; /* Printing width of standout seq */
199 public int bl_s_width, bl_e_width; /* Printing width of blink seq */
200 public int above_mem, below_mem; /* Memory retained above/below screen */
201 public int can_goto_line; /* Can move cursor to any line */
202 public int clear_bg; /* Clear fills with background color */
203 public int missing_cap = 0; /* Some capability is missing */
204
205 static int attrmode = AT_NORMAL;
206 extern int binattr;
207
208 #if !MSDOS_COMPILER
209 static char *cheaper();
210 static void tmodes();
211 #endif
212
213 /*
214 * These two variables are sometimes defined in,
215 * and needed by, the termcap library.
216 */
217 #if MUST_DEFINE_OSPEED
218 extern short ospeed; /* Terminal output baud rate */
219 extern char PC; /* Pad character */
220 #endif
221 #ifdef _OSK
222 short ospeed;
223 char PC_, *UP, *BC;
224 #endif
225
226 extern int quiet; /* If VERY_QUIET, use visual bell for bell */
227 extern int no_back_scroll;
228 extern int swindow;
229 extern int no_init;
230 extern int no_keypad;
231 extern int sigs;
232 extern int wscroll;
233 extern int screen_trashed;
234 extern int tty;
235 extern int top_scroll;
236 extern int oldbot;
237 #if HILITE_SEARCH
238 extern int hilite_search;
239 #endif
240
241 extern char *tgetstr();
242 extern char *tgoto();
243
244
245 /*
246 * Change terminal to "raw mode", or restore to "normal" mode.
247 * "Raw mode" means
248 * 1. An outstanding read will complete on receipt of a single keystroke.
249 * 2. Input is not echoed.
250 * 3. On output, \n is mapped to \r\n.
251 * 4. \t is NOT expanded into spaces.
252 * 5. Signal-causing characters such as ctrl-C (interrupt),
253 * etc. are NOT disabled.
254 * It doesn't matter whether an input \n is mapped to \r, or vice versa.
255 */
256 public void
257 raw_mode(on)
258 int on;
259 {
260 static int curr_on = 0;
261
262 if (on == curr_on)
263 return;
264 erase2_char = '\b'; /* in case OS doesn't know about erase2 */
265 #if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS
266 {
267 struct termios s;
268 static struct termios save_term;
269 static int saved_term = 0;
270
271 if (on)
272 {
273 /*
274 * Get terminal modes.
275 */
276 tcgetattr(tty, &s);
277
278 /*
279 * Save modes and set certain variables dependent on modes.
280 */
281 if (!saved_term)
282 {
283 save_term = s;
284 saved_term = 1;
285 }
286 #if HAVE_OSPEED
287 switch (cfgetospeed(&s))
288 {
289 #ifdef B0
290 case B0: ospeed = 0; break;
291 #endif
292 #ifdef B50
293 case B50: ospeed = 1; break;
294 #endif
295 #ifdef B75
296 case B75: ospeed = 2; break;
297 #endif
298 #ifdef B110
299 case B110: ospeed = 3; break;
300 #endif
301 #ifdef B134
302 case B134: ospeed = 4; break;
303 #endif
304 #ifdef B150
305 case B150: ospeed = 5; break;
306 #endif
307 #ifdef B200
308 case B200: ospeed = 6; break;
309 #endif
310 #ifdef B300
311 case B300: ospeed = 7; break;
312 #endif
313 #ifdef B600
314 case B600: ospeed = 8; break;
315 #endif
316 #ifdef B1200
317 case B1200: ospeed = 9; break;
318 #endif
319 #ifdef B1800
320 case B1800: ospeed = 10; break;
321 #endif
322 #ifdef B2400
323 case B2400: ospeed = 11; break;
324 #endif
325 #ifdef B4800
326 case B4800: ospeed = 12; break;
327 #endif
328 #ifdef B9600
329 case B9600: ospeed = 13; break;
330 #endif
331 #ifdef EXTA
332 case EXTA: ospeed = 14; break;
333 #endif
334 #ifdef EXTB
335 case EXTB: ospeed = 15; break;
336 #endif
337 #ifdef B57600
338 case B57600: ospeed = 16; break;
339 #endif
340 #ifdef B115200
341 case B115200: ospeed = 17; break;
342 #endif
343 default: ;
344 }
345 #endif
346 erase_char = s.c_cc[VERASE];
347 #ifdef VERASE2
348 erase2_char = s.c_cc[VERASE2];
349 #endif
350 kill_char = s.c_cc[VKILL];
351 #ifdef VWERASE
352 werase_char = s.c_cc[VWERASE];
353 #else
354 werase_char = CONTROL('W');
355 #endif
356
357 /*
358 * Set the modes to the way we want them.
359 */
360 s.c_lflag &= ~(0
361 #ifdef ICANON
362 | ICANON
363 #endif
364 #ifdef ECHO
365 | ECHO
366 #endif
367 #ifdef ECHOE
368 | ECHOE
369 #endif
370 #ifdef ECHOK
371 | ECHOK
372 #endif
373 #if ECHONL
374 | ECHONL
375 #endif
376 );
377
378 s.c_oflag |= (0
379 #ifdef OXTABS
380 | OXTABS
381 #else
382 #ifdef TAB3
383 | TAB3
384 #else
385 #ifdef XTABS
386 | XTABS
387 #endif
388 #endif
389 #endif
390 #ifdef OPOST
391 | OPOST
392 #endif
393 #ifdef ONLCR
394 | ONLCR
395 #endif
396 );
397
398 s.c_oflag &= ~(0
399 #ifdef ONOEOT
400 | ONOEOT
401 #endif
402 #ifdef OCRNL
403 | OCRNL
404 #endif
405 #ifdef ONOCR
406 | ONOCR
407 #endif
408 #ifdef ONLRET
409 | ONLRET
410 #endif
411 );
412 s.c_cc[VMIN] = 1;
413 s.c_cc[VTIME] = 0;
414 #ifdef VLNEXT
415 s.c_cc[VLNEXT] = 0;
416 #endif
417 #ifdef VDSUSP
418 s.c_cc[VDSUSP] = 0;
419 #endif
420 #if MUST_SET_LINE_DISCIPLINE
421 /*
422 * System's termios is broken; need to explicitly
423 * request TERMIODISC line discipline.
424 */
425 s.c_line = TERMIODISC;
426 #endif
427 } else
428 {
429 /*
430 * Restore saved modes.
431 */
432 s = save_term;
433 }
434 #if HAVE_FSYNC
435 fsync(tty);
436 #endif
437 tcsetattr(tty, TCSADRAIN, &s);
438 #if MUST_SET_LINE_DISCIPLINE
439 if (!on)
440 {
441 /*
442 * Broken termios *ignores* any line discipline
443 * except TERMIODISC. A different old line discipline
444 * is therefore not restored, yet. Restore the old
445 * line discipline by hand.
446 */
447 ioctl(tty, TIOCSETD, &save_term.c_line);
448 }
449 #endif
450 }
451 #else
452 #ifdef TCGETA
453 {
454 struct termio s;
455 static struct termio save_term;
456 static int saved_term = 0;
457
458 if (on)
459 {
460 /*
461 * Get terminal modes.
462 */
463 ioctl(tty, TCGETA, &s);
464
465 /*
466 * Save modes and set certain variables dependent on modes.
467 */
468 if (!saved_term)
469 {
470 save_term = s;
471 saved_term = 1;
472 }
473 #if HAVE_OSPEED
474 ospeed = s.c_cflag & CBAUD;
475 #endif
476 erase_char = s.c_cc[VERASE];
477 kill_char = s.c_cc[VKILL];
478 #ifdef VWERASE
479 werase_char = s.c_cc[VWERASE];
480 #else
481 werase_char = CONTROL('W');
482 #endif
483
484 /*
485 * Set the modes to the way we want them.
486 */
487 s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
488 s.c_oflag |= (OPOST|ONLCR|TAB3);
489 s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
490 s.c_cc[VMIN] = 1;
491 s.c_cc[VTIME] = 0;
492 } else
493 {
494 /*
495 * Restore saved modes.
496 */
497 s = save_term;
498 }
499 ioctl(tty, TCSETAW, &s);
500 }
501 #else
502 #ifdef TIOCGETP
503 {
504 struct sgttyb s;
505 static struct sgttyb save_term;
506 static int saved_term = 0;
507
508 if (on)
509 {
510 /*
511 * Get terminal modes.
512 */
513 ioctl(tty, TIOCGETP, &s);
514
515 /*
516 * Save modes and set certain variables dependent on modes.
517 */
518 if (!saved_term)
519 {
520 save_term = s;
521 saved_term = 1;
522 }
523 #if HAVE_OSPEED
524 ospeed = s.sg_ospeed;
525 #endif
526 erase_char = s.sg_erase;
527 kill_char = s.sg_kill;
528 werase_char = CONTROL('W');
529
530 /*
531 * Set the modes to the way we want them.
532 */
533 s.sg_flags |= CBREAK;
534 s.sg_flags &= ~(ECHO|XTABS);
535 } else
536 {
537 /*
538 * Restore saved modes.
539 */
540 s = save_term;
541 }
542 ioctl(tty, TIOCSETN, &s);
543 }
544 #else
545 #ifdef _OSK
546 {
547 struct sgbuf s;
548 static struct sgbuf save_term;
549 static int saved_term = 0;
550
551 if (on)
552 {
553 /*
554 * Get terminal modes.
555 */
556 _gs_opt(tty, &s);
557
558 /*
559 * Save modes and set certain variables dependent on modes.
560 */
561 if (!saved_term)
562 {
563 save_term = s;
564 saved_term = 1;
565 }
566 erase_char = s.sg_bspch;
567 kill_char = s.sg_dlnch;
568 werase_char = CONTROL('W');
569
570 /*
571 * Set the modes to the way we want them.
572 */
573 s.sg_echo = 0;
574 s.sg_eofch = 0;
575 s.sg_pause = 0;
576 s.sg_psch = 0;
577 } else
578 {
579 /*
580 * Restore saved modes.
581 */
582 s = save_term;
583 }
584 _ss_opt(tty, &s);
585 }
586 #else
587 /* MS-DOS, Windows, or OS2 */
588 #if OS2
589 /* OS2 */
590 LSIGNAL(SIGINT, SIG_IGN);
591 #endif
592 erase_char = '\b';
593 #if MSDOS_COMPILER==DJGPPC
594 kill_char = CONTROL('U');
595 /*
596 * So that when we shell out or run another program, its
597 * stdin is in cooked mode. We do not switch stdin to binary
598 * mode if fd0 is zero, since that means we were called before
599 * tty was reopened in open_getchr, in which case we would be
600 * changing the original stdin device outside less.
601 */
602 if (fd0 != 0)
603 setmode(0, on ? O_BINARY : O_TEXT);
604 #else
605 kill_char = ESC;
606 #endif
607 werase_char = CONTROL('W');
608 #endif
609 #endif
610 #endif
611 #endif
612 curr_on = on;
613 }
614
615 #if !MSDOS_COMPILER
616 /*
617 * Some glue to prevent calling termcap functions if tgetent() failed.
618 */
619 static int hardcopy;
620
621 static char *
622 ltget_env(capname)
623 char *capname;
624 {
625 char name[16];
626 char *s;
627
628 s = lgetenv("LESS_TERMCAP_DEBUG");
629 if (s != NULL && *s != '\0')
630 {
631 struct env { struct env *next; char *name; char *value; };
632 static struct env *envs = NULL;
633 struct env *p;
634 for (p = envs; p != NULL; p = p->next)
635 if (strcmp(p->name, capname) == 0)
636 return p->value;
637 p = (struct env *) ecalloc(1, sizeof(struct env));
638 p->name = save(capname);
639 p->value = (char *) ecalloc(strlen(capname)+3, sizeof(char));
640 sprintf(p->value, "<%s>", capname);
641 p->next = envs;
642 envs = p;
643 return p->value;
644 }
645 strcpy(name, "LESS_TERMCAP_");
646 strcat(name, capname);
647 return (lgetenv(name));
648 }
649
650 static int
651 ltgetflag(capname)
652 char *capname;
653 {
654 char *s;
655
656 if ((s = ltget_env(capname)) != NULL)
657 return (*s != '\0' && *s != '0');
658 if (hardcopy)
659 return (0);
660 return (tgetflag(capname));
661 }
662
663 static int
664 ltgetnum(capname)
665 char *capname;
666 {
667 char *s;
668
669 if ((s = ltget_env(capname)) != NULL)
670 return (atoi(s));
671 if (hardcopy)
672 return (-1);
673 return (tgetnum(capname));
674 }
675
676 static char *
677 ltgetstr(capname, pp)
678 char *capname;
679 char **pp;
680 {
681 char *s;
682
683 if ((s = ltget_env(capname)) != NULL)
684 return (s);
685 if (hardcopy)
686 return (NULL);
687 return (tgetstr(capname, pp));
688 }
689 #endif /* MSDOS_COMPILER */
690
691 /*
692 * Get size of the output screen.
693 */
694 public void
695 scrsize()
696 {
697 register char *s;
698 int sys_height;
699 int sys_width;
700 #if !MSDOS_COMPILER
701 int n;
702 #endif
703
704 #define DEF_SC_WIDTH 80
705 #if MSDOS_COMPILER
706 #define DEF_SC_HEIGHT 25
707 #else
708 #define DEF_SC_HEIGHT 24
709 #endif
710
711
712 sys_width = sys_height = 0;
713
714 #if MSDOS_COMPILER==MSOFTC
715 {
716 struct videoconfig w;
717 _getvideoconfig(&w);
718 sys_height = w.numtextrows;
719 sys_width = w.numtextcols;
720 }
721 #else
722 #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
723 {
724 struct text_info w;
725 gettextinfo(&w);
726 sys_height = w.screenheight;
727 sys_width = w.screenwidth;
728 }
729 #else
730 #if MSDOS_COMPILER==WIN32C
731 {
732 CONSOLE_SCREEN_BUFFER_INFO scr;
733 GetConsoleScreenBufferInfo(con_out, &scr);
734 sys_height = scr.srWindow.Bottom - scr.srWindow.Top + 1;
735 sys_width = scr.srWindow.Right - scr.srWindow.Left + 1;
736 }
737 #else
738 #if OS2
739 {
740 int s[2];
741 _scrsize(s);
742 sys_width = s[0];
743 sys_height = s[1];
744 /*
745 * When using terminal emulators for XFree86/OS2, the
746 * _scrsize function does not work well.
747 * Call the scrsize.exe program to get the window size.
748 */
749 windowid = getenv("WINDOWID");
750 if (windowid != NULL)
751 {
752 FILE *fd = popen("scrsize", "rt");
753 if (fd != NULL)
754 {
755 int w, h;
756 fscanf(fd, "%i %i", &w, &h);
757 if (w > 0 && h > 0)
758 {
759 sys_width = w;
760 sys_height = h;
761 }
762 pclose(fd);
763 }
764 }
765 }
766 #else
767 #ifdef TIOCGWINSZ
768 {
769 struct winsize w;
770 if (ioctl(2, TIOCGWINSZ, &w) == 0)
771 {
772 if (w.ws_row > 0)
773 sys_height = w.ws_row;
774 if (w.ws_col > 0)
775 sys_width = w.ws_col;
776 }
777 }
778 #else
779 #ifdef WIOCGETD
780 {
781 struct uwdata w;
782 if (ioctl(2, WIOCGETD, &w) == 0)
783 {
784 if (w.uw_height > 0)
785 sys_height = w.uw_height / w.uw_vs;
786 if (w.uw_width > 0)
787 sys_width = w.uw_width / w.uw_hs;
788 }
789 }
790 #endif
791 #endif
792 #endif
793 #endif
794 #endif
795 #endif
796
797 if (sys_height > 0)
798 sc_height = sys_height;
799 else if ((s = lgetenv("LINES")) != NULL)
800 sc_height = atoi(s);
801 #if !MSDOS_COMPILER
802 else if ((n = ltgetnum("li")) > 0)
803 sc_height = n;
804 #endif
805 else
806 sc_height = DEF_SC_HEIGHT;
807
808 if (sys_width > 0)
809 sc_width = sys_width;
810 else if ((s = lgetenv("COLUMNS")) != NULL)
811 sc_width = atoi(s);
812 #if !MSDOS_COMPILER
813 else if ((n = ltgetnum("co")) > 0)
814 sc_width = n;
815 #endif
816 else
817 sc_width = DEF_SC_WIDTH;
818 }
819
820 #if MSDOS_COMPILER==MSOFTC
821 /*
822 * Figure out how many empty loops it takes to delay a millisecond.
823 */
824 static void
825 get_clock()
826 {
827 clock_t start;
828
829 /*
830 * Get synchronized at the start of a tick.
831 */
832 start = clock();
833 while (clock() == start)
834 ;
835 /*
836 * Now count loops till the next tick.
837 */
838 start = clock();
839 msec_loops = 0;
840 while (clock() == start)
841 msec_loops++;
842 /*
843 * Convert from (loops per clock) to (loops per millisecond).
844 */
845 msec_loops *= CLOCKS_PER_SEC;
846 msec_loops /= 1000;
847 }
848
849 /*
850 * Delay for a specified number of milliseconds.
851 */
852 static void
853 dummy_func()
854 {
855 static long delay_dummy = 0;
856 delay_dummy++;
857 }
858
859 static void
860 delay(msec)
861 int msec;
862 {
863 long i;
864
865 while (msec-- > 0)
866 {
867 for (i = 0; i < msec_loops; i++)
868 {
869 /*
870 * Make it look like we're doing something here,
871 * so the optimizer doesn't remove the whole loop.
872 */
873 dummy_func();
874 }
875 }
876 }
877 #endif
878
879 /*
880 * Return the characters actually input by a "special" key.
881 */
882 public char *
883 special_key_str(key)
884 int key;
885 {
886 static char tbuf[40];
887 char *s;
888 #if MSDOS_COMPILER || OS2
889 static char k_right[] = { '\340', PCK_RIGHT, 0 };
890 static char k_left[] = { '\340', PCK_LEFT, 0 };
891 static char k_ctl_right[] = { '\340', PCK_CTL_RIGHT, 0 };
892 static char k_ctl_left[] = { '\340', PCK_CTL_LEFT, 0 };
893 static char k_insert[] = { '\340', PCK_INSERT, 0 };
894 static char k_delete[] = { '\340', PCK_DELETE, 0 };
895 static char k_ctl_delete[] = { '\340', PCK_CTL_DELETE, 0 };
896 static char k_ctl_backspace[] = { '\177', 0 };
897 static char k_home[] = { '\340', PCK_HOME, 0 };
898 static char k_end[] = { '\340', PCK_END, 0 };
899 static char k_up[] = { '\340', PCK_UP, 0 };
900 static char k_down[] = { '\340', PCK_DOWN, 0 };
901 static char k_backtab[] = { '\340', PCK_SHIFT_TAB, 0 };
902 static char k_pagedown[] = { '\340', PCK_PAGEDOWN, 0 };
903 static char k_pageup[] = { '\340', PCK_PAGEUP, 0 };
904 static char k_f1[] = { '\340', PCK_F1, 0 };
905 #endif
906 #if !MSDOS_COMPILER
907 char *sp = tbuf;
908 #endif
909
910 switch (key)
911 {
912 #if OS2
913 /*
914 * If windowid is not NULL, assume less is executed in
915 * the XFree86 environment.
916 */
917 case SK_RIGHT_ARROW:
918 s = windowid ? ltgetstr("kr", &sp) : k_right;
919 break;
920 case SK_LEFT_ARROW:
921 s = windowid ? ltgetstr("kl", &sp) : k_left;
922 break;
923 case SK_UP_ARROW:
924 s = windowid ? ltgetstr("ku", &sp) : k_up;
925 break;
926 case SK_DOWN_ARROW:
927 s = windowid ? ltgetstr("kd", &sp) : k_down;
928 break;
929 case SK_PAGE_UP:
930 s = windowid ? ltgetstr("kP", &sp) : k_pageup;
931 break;
932 case SK_PAGE_DOWN:
933 s = windowid ? ltgetstr("kN", &sp) : k_pagedown;
934 break;
935 case SK_HOME:
936 s = windowid ? ltgetstr("kh", &sp) : k_home;
937 break;
938 case SK_END:
939 s = windowid ? ltgetstr("@7", &sp) : k_end;
940 break;
941 case SK_DELETE:
942 if (windowid)
943 {
944 s = ltgetstr("kD", &sp);
945 if (s == NULL)
946 {
947 tbuf[0] = '\177';
948 tbuf[1] = '\0';
949 s = tbuf;
950 }
951 } else
952 s = k_delete;
953 break;
954 #endif
955 #if MSDOS_COMPILER
956 case SK_RIGHT_ARROW:
957 s = k_right;
958 break;
959 case SK_LEFT_ARROW:
960 s = k_left;
961 break;
962 case SK_UP_ARROW:
963 s = k_up;
964 break;
965 case SK_DOWN_ARROW:
966 s = k_down;
967 break;
968 case SK_PAGE_UP:
969 s = k_pageup;
970 break;
971 case SK_PAGE_DOWN:
972 s = k_pagedown;
973 break;
974 case SK_HOME:
975 s = k_home;
976 break;
977 case SK_END:
978 s = k_end;
979 break;
980 case SK_DELETE:
981 s = k_delete;
982 break;
983 #endif
984 #if MSDOS_COMPILER || OS2
985 case SK_INSERT:
986 s = k_insert;
987 break;
988 case SK_CTL_LEFT_ARROW:
989 s = k_ctl_left;
990 break;
991 case SK_CTL_RIGHT_ARROW:
992 s = k_ctl_right;
993 break;
994 case SK_CTL_BACKSPACE:
995 s = k_ctl_backspace;
996 break;
997 case SK_CTL_DELETE:
998 s = k_ctl_delete;
999 break;
1000 case SK_F1:
1001 s = k_f1;
1002 break;
1003 case SK_BACKTAB:
1004 s = k_backtab;
1005 break;
1006 #else
1007 case SK_RIGHT_ARROW:
1008 s = ltgetstr("kr", &sp);
1009 break;
1010 case SK_LEFT_ARROW:
1011 s = ltgetstr("kl", &sp);
1012 break;
1013 case SK_UP_ARROW:
1014 s = ltgetstr("ku", &sp);
1015 break;
1016 case SK_DOWN_ARROW:
1017 s = ltgetstr("kd", &sp);
1018 break;
1019 case SK_PAGE_UP:
1020 s = ltgetstr("kP", &sp);
1021 break;
1022 case SK_PAGE_DOWN:
1023 s = ltgetstr("kN", &sp);
1024 break;
1025 case SK_HOME:
1026 s = ltgetstr("kh", &sp);
1027 break;
1028 case SK_END:
1029 s = ltgetstr("@7", &sp);
1030 break;
1031 case SK_DELETE:
1032 s = ltgetstr("kD", &sp);
1033 if (s == NULL)
1034 {
1035 tbuf[0] = '\177';
1036 tbuf[1] = '\0';
1037 s = tbuf;
1038 }
1039 break;
1040 #endif
1041 case SK_CONTROL_K:
1042 tbuf[0] = CONTROL('K');
1043 tbuf[1] = '\0';
1044 s = tbuf;
1045 break;
1046 default:
1047 return (NULL);
1048 }
1049 return (s);
1050 }
1051
1052 /*
1053 * Get terminal capabilities via termcap.
1054 */
1055 public void
1056 get_term()
1057 {
1058 #if MSDOS_COMPILER
1059 auto_wrap = 1;
1060 ignaw = 0;
1061 can_goto_line = 1;
1062 clear_bg = 1;
1063 /*
1064 * Set up default colors.
1065 * The xx_s_width and xx_e_width vars are already initialized to 0.
1066 */
1067 #if MSDOS_COMPILER==MSOFTC
1068 sy_bg_color = _getbkcolor();
1069 sy_fg_color = _gettextcolor();
1070 get_clock();
1071 #else
1072 #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
1073 {
1074 struct text_info w;
1075 gettextinfo(&w);
1076 sy_bg_color = (w.attribute >> 4) & 0x0F;
1077 sy_fg_color = (w.attribute >> 0) & 0x0F;
1078 }
1079 #else
1080 #if MSDOS_COMPILER==WIN32C
1081 {
1082 DWORD nread;
1083 CONSOLE_SCREEN_BUFFER_INFO scr;
1084
1085 con_out_save = con_out = GetStdHandle(STD_OUTPUT_HANDLE);
1086 /*
1087 * Always open stdin in binary. Note this *must* be done
1088 * before any file operations have been done on fd0.
1089 */
1090 SET_BINARY(0);
1091 GetConsoleScreenBufferInfo(con_out, &scr);
1092 ReadConsoleOutputAttribute(con_out, &curr_attr,
1093 1, scr.dwCursorPosition