=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/less/screen.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- src/usr.bin/less/screen.c 2005/04/11 19:59:07 1.14 +++ src/usr.bin/less/screen.c 2011/09/16 18:12:09 1.15 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2002 Mark Nudelman + * Copyright (C) 1984-2011 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -38,11 +38,12 @@ #else -#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS -#include #if HAVE_SYS_IOCTL_H #include #endif + +#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS +#include #else #if HAVE_TERMIO_H #include @@ -52,11 +53,8 @@ #else #include #endif -#if HAVE_SYS_IOCTL_H && (defined(TIOCGWINSZ) || defined(TCGETA) || defined(TIOCGETP) || defined(WIOCGETD)) -#include #endif #endif -#endif #if HAVE_TERMCAP_H #include @@ -165,6 +163,7 @@ *sc_home, /* Cursor home */ *sc_addline, /* Add line, scroll down following lines */ *sc_lower_left, /* Cursor to last line, first column */ + *sc_return, /* Cursor to beginning of current line */ *sc_move, /* General cursor positioning */ *sc_clear, /* Clear screen */ *sc_eol_clear, /* Clear to end of line */ @@ -189,7 +188,9 @@ public int auto_wrap; /* Terminal does \r\n when write past margin */ public int ignaw; /* Terminal ignores \n immediately after wrap */ -public int erase_char, kill_char; /* The user's erase and line-kill chars */ +public int erase_char; /* The user's erase char */ +public int erase2_char; /* The user's other erase char */ +public int kill_char; /* The user's line-kill char */ public int werase_char; /* The user's word-erase char */ public int sc_width, sc_height; /* Height & width of screen */ public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ @@ -202,6 +203,7 @@ public int missing_cap = 0; /* Some capability is missing */ static int attrmode = AT_NORMAL; +extern int binattr; #if !MSDOS_COMPILER static char *cheaper(); @@ -230,8 +232,8 @@ extern int wscroll; extern int screen_trashed; extern int tty; -extern int quit_at_eof; -extern int ismore; +extern int top_scroll; +extern int oldbot; #if HILITE_SEARCH extern int hilite_search; #endif @@ -259,6 +261,7 @@ if (on == curr_on) return; + erase2_char = '\b'; /* in case OS doesn't know about erase2 */ #if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS { struct termios s; @@ -341,6 +344,9 @@ } #endif erase_char = s.c_cc[VERASE]; +#ifdef VERASE2 + erase2_char = s.c_cc[VERASE2]; +#endif kill_char = s.c_cc[VKILL]; #ifdef VWERASE werase_char = s.c_cc[VWERASE]; @@ -617,7 +623,27 @@ char *capname; { char name[16]; + char *s; + s = lgetenv("LESS_TERMCAP_DEBUG"); + if (s != NULL && *s != '\0') + { + struct env { struct env *next; char *name; char *value; }; + static struct env *envs = NULL; + struct env *p; + size_t len; + for (p = envs; p != NULL; p = p->next) + if (strcmp(p->name, capname) == 0) + return p->value; + p = (struct env *) ecalloc(1, sizeof(struct env)); + p->name = save(capname); + len = strlen(capname) + 3; + p->value = (char *) ecalloc(len, sizeof(char)); + snprintf(p->value, len, "<%s>", capname); + p->next = envs; + envs = p; + return p->value; + } strlcpy(name, "LESS_TERMCAP_", sizeof(name)); strlcat(name, capname, sizeof(name)); return (lgetenv(name)); @@ -1124,7 +1150,7 @@ if ((term = lgetenv("TERM")) == NULL) term = DEFAULT_TERM; hardcopy = 0; - if (tgetent(termbuf, term) <= 0) + if (tgetent(termbuf, term) != TGETENT_OK) hardcopy = 1; if (ltgetflag("hc")) hardcopy = 1; @@ -1185,18 +1211,11 @@ if (sc_e_keypad == NULL) sc_e_keypad = ""; - /* - * This loses for terminals with termcap entries with ti/te strings - * that switch to/from an alternate screen, and we're in quit_at_eof - * (eg, more(1)). - */ - if (!quit_at_eof && !ismore) { - sc_init = ltgetstr("ti", &sp); - sc_deinit= ltgetstr("te", &sp); - } + sc_init = ltgetstr("ti", &sp); if (sc_init == NULL) sc_init = ""; + sc_deinit= ltgetstr("te", &sp); if (sc_deinit == NULL) sc_deinit = ""; @@ -1211,7 +1230,7 @@ if (below_mem && (sc_eos_clear == NULL || *sc_eos_clear == '\0')) { missing_cap = 1; - sc_eol_clear = ""; + sc_eos_clear = ""; } sc_clear = ltgetstr("cl", &sp); @@ -1288,6 +1307,13 @@ sc_lower_left = cheaper(t1, t2, "\r"); /* + * Get carriage return string. + */ + sc_return = ltgetstr("cr", &sp); + if (sc_return == NULL) + sc_return = "\r"; + + /* * Choose between using "al" or "sr" ("add line" or "scroll reverse") * to add a line at the top of the screen. */ @@ -1516,6 +1542,20 @@ tputs(sc_init, sc_height, putchr); if (!no_keypad) tputs(sc_s_keypad, sc_height, putchr); + if (top_scroll) + { + int i; + + /* + * This is nice to terminals with no alternate screen, + * but with saved scrolled-off-the-top lines. This way, + * no previous line is lost, but we start with a whole + * screen to ourself. + */ + for (i = 1; i < sc_height; i++) + putchr('\n'); + } else + line_left(); #else #if MSDOS_COMPILER==WIN32C if (!no_init) @@ -1752,7 +1792,7 @@ /* Move the source text to the top of the screen. */ new_org.X = rcSrc.Left; - new_org.Y = 0; + new_org.Y = rcClip.Top; /* Fill the right character and attributes. */ fillchar.Char.AsciiChar = ' '; @@ -1793,6 +1833,37 @@ } /* + * Move cursor to left position of current line. + */ + public void +line_left() +{ +#if !MSDOS_COMPILER + tputs(sc_return, 1, putchr); +#else + int row; + flush(); +#if MSDOS_COMPILER==WIN32C + { + CONSOLE_SCREEN_BUFFER_INFO scr; + GetConsoleScreenBufferInfo(con_out, &scr); + row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; + } +#else +#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC + row = wherey(); +#else + { + struct rccoord tpos = _gettextposition(); + row = tpos.row; + } +#endif +#endif + _settextposition(row, 1); +#endif +} + +/* * Check if the console size has changed and reset internals * (in lieu of SIGWINCH for WIN32). */ @@ -1857,12 +1928,12 @@ videopages = w.numvideopages; if (videopages < 2) { - so_enter(); - so_exit(); + at_enter(AT_STANDOUT); + at_exit(); } else { _setactivepage(1); - so_enter(); + at_enter(AT_STANDOUT); blanks = (char *) ecalloc(w.numtextcols, sizeof(char)); for (col = 0; col < w.numtextcols; col++) blanks[col] = ' '; @@ -1871,7 +1942,7 @@ _setactivepage(0); _setvisualpage(0); free(blanks); - so_exit(); + at_exit(); } #else #if MSDOS_COMPILER==BORLANDC @@ -2100,154 +2171,119 @@ * the mode while we do the clear. Some terminals fill the * cleared area with the current attribute. */ - lower_left(); - switch (attrmode) + if (oldbot) + lower_left(); + else + line_left(); + + if (attrmode == AT_NORMAL) + clear_eol_bot(); + else { - case AT_STANDOUT: - so_exit(); + int saved_attrmode = attrmode; + + at_exit(); clear_eol_bot(); - so_enter(); - break; - case AT_UNDERLINE: - ul_exit(); - clear_eol_bot(); - ul_enter(); - break; - case AT_BOLD: - bo_exit(); - clear_eol_bot(); - bo_enter(); - break; - case AT_BLINK: - bl_exit(); - clear_eol_bot(); - bl_enter(); - break; - default: - clear_eol_bot(); - break; + at_enter(saved_attrmode); } } -/* - * Begin "standout" (bold, underline, or whatever). - */ public void -so_enter() +at_enter(attr) + int attr; { -#if !MSDOS_COMPILER - tputs(sc_s_in, 1, putchr); -#else - flush(); - SETCOLORS(so_fg_color, so_bg_color); -#endif - attrmode = AT_STANDOUT; -} + attr = apply_at_specials(attr); -/* - * End "standout". - */ - public void -so_exit() -{ #if !MSDOS_COMPILER - tputs(sc_s_out, 1, putchr); + /* The one with the most priority is last. */ + if (attr & AT_UNDERLINE) + tputs(sc_u_in, 1, putchr); + if (attr & AT_BOLD) + tputs(sc_b_in, 1, putchr); + if (attr & AT_BLINK) + tputs(sc_bl_in, 1, putchr); + if (attr & AT_STANDOUT) + tputs(sc_s_in, 1, putchr); #else flush(); - SETCOLORS(nm_fg_color, nm_bg_color); + /* The one with the most priority is first. */ + if (attr & AT_STANDOUT) + { + SETCOLORS(so_fg_color, so_bg_color); + } else if (attr & AT_BLINK) + { + SETCOLORS(bl_fg_color, bl_bg_color); + } + else if (attr & AT_BOLD) + { + SETCOLORS(bo_fg_color, bo_bg_color); + } + else if (attr & AT_UNDERLINE) + { + SETCOLORS(ul_fg_color, ul_bg_color); + } #endif - attrmode = AT_NORMAL; -} -/* - * Begin "underline" (hopefully real underlining, - * otherwise whatever the terminal provides). - */ - public void -ul_enter() -{ -#if !MSDOS_COMPILER - tputs(sc_u_in, 1, putchr); -#else - flush(); - SETCOLORS(ul_fg_color, ul_bg_color); -#endif - attrmode = AT_UNDERLINE; + attrmode = attr; } -/* - * End "underline". - */ public void -ul_exit() +at_exit() { #if !MSDOS_COMPILER - tputs(sc_u_out, 1, putchr); + /* Undo things in the reverse order we did them. */ + if (attrmode & AT_STANDOUT) + tputs(sc_s_out, 1, putchr); + if (attrmode & AT_BLINK) + tputs(sc_bl_out, 1, putchr); + if (attrmode & AT_BOLD) + tputs(sc_b_out, 1, putchr); + if (attrmode & AT_UNDERLINE) + tputs(sc_u_out, 1, putchr); #else flush(); SETCOLORS(nm_fg_color, nm_bg_color); #endif + attrmode = AT_NORMAL; } -/* - * Begin "bold" - */ public void -bo_enter() +at_switch(attr) + int attr; { -#if !MSDOS_COMPILER - tputs(sc_b_in, 1, putchr); -#else - flush(); - SETCOLORS(bo_fg_color, bo_bg_color); -#endif - attrmode = AT_BOLD; -} + int new_attrmode = apply_at_specials(attr); + int ignore_modes = AT_ANSI; -/* - * End "bold". - */ - public void -bo_exit() -{ -#if !MSDOS_COMPILER - tputs(sc_b_out, 1, putchr); -#else - flush(); - SETCOLORS(nm_fg_color, nm_bg_color); -#endif - attrmode = AT_NORMAL; + if ((new_attrmode & ~ignore_modes) != (attrmode & ~ignore_modes)) + { + at_exit(); + at_enter(attr); + } } -/* - * Begin "blink" - */ - public void -bl_enter() + public int +is_at_equiv(attr1, attr2) + int attr1; + int attr2; { -#if !MSDOS_COMPILER - tputs(sc_bl_in, 1, putchr); -#else - flush(); - SETCOLORS(bl_fg_color, bl_bg_color); -#endif - attrmode = AT_BLINK; + attr1 = apply_at_specials(attr1); + attr2 = apply_at_specials(attr2); + + return (attr1 == attr2); } -/* - * End "blink". - */ - public void -bl_exit() + public int +apply_at_specials(attr) + int attr; { -#if !MSDOS_COMPILER - tputs(sc_bl_out, 1, putchr); -#else - flush(); - SETCOLORS(nm_fg_color, nm_bg_color); -#endif - attrmode = AT_NORMAL; + if (attr & AT_BINARY) + attr |= binattr; + if (attr & AT_HILITE) + attr |= AT_STANDOUT; + attr &= ~(AT_BINARY|AT_HILITE); + + return attr; } #if 0 /* No longer used */ @@ -2436,5 +2472,35 @@ */ pending_scancode = (ascii == 0x00); return ((char)ascii); +} +#endif + +#if MSDOS_COMPILER +/* + */ + public void +WIN32setcolors(fg, bg) + int fg; + int bg; +{ + SETCOLORS(fg, bg); +} + +/* + */ + public void +WIN32textout(text, len) + char *text; + int len; +{ +#if MSDOS_COMPILER==WIN32C + DWORD written; + WriteConsole(con_out, text, len, &written, NULL); +#else + char c = text[len]; + text[len] = '\0'; + cputs(text); + text[len] = c; +#endif } #endif