=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/less/prompt.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- src/usr.bin/less/prompt.c 2003/04/06 23:38:07 1.6 +++ src/usr.bin/less/prompt.c 2003/04/13 18:26:26 1.7 @@ -1,29 +1,11 @@ -/* $OpenBSD: prompt.c,v 1.6 2003/04/06 23:38:07 deraadt Exp $ */ - /* - * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman - * All rights reserved. + * Copyright (C) 1984-2002 Mark Nudelman * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice in the documentation and/or other materials provided with - * the distribution. + * You may distribute under the terms of either the GNU General Public + * License or the Less License, as specified in the README file. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * For more information about less, or for information on how to + * contact the author, see the README file. */ @@ -45,30 +27,41 @@ extern int sc_width; extern int so_s_width, so_e_width; extern int linenums; +extern int hshift; +extern int ismore; extern int sc_height; extern int jump_sline; extern IFILE curr_ifile; #if EDITOR extern char *editor; +extern char *editproto; #endif /* * Prototypes for the three flavors of prompts. * These strings are expanded by pr_expand(). */ -static char s_proto[] = - "?n?f%f .?m(file %i of %m) ..?e(END) ?x- Next\\: %x..%t"; -static char m_proto[] = - "?f%f .?m(file %i of %m) .?e(END) ?x- Next\\: %x.:(?pB%pB\\%:byte %bB?s/%s..).%t"; -static char M_proto[] = - "?f%f .?n?m(file %i of %m) ..?ltline %lt?L/%L. :byte %bB?s/%s. .?e(END) ?x- Next\\: %x.:?pB%pB\\%..%t"; -static char e_proto[] = - "?f%f .?m(file %i of %m) .?ltline %lt?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t"; +static constant char s_proto[] = + "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x..%t"; +static constant char m_proto[] = + "?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t"; +static constant char M_proto[] = + "?f%f .?n?m(%T %i of %m) ..?ltlines %lt-%lb?L/%L. :byte %bB?s/%s. .?e(END) ?x- Next\\: %x.:?pB%pB\\%..%t"; +static constant char more_proto[] = + "--More--.?e(END) ?x- Next\\: %x.:(?pB%pB\\%:byte %bB?s/%s..).%t"; +static constant char e_proto[] = + "?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t"; +static constant char h_proto[] = + "HELP -- ?eEND -- Press g to see it again:Press RETURN for more., or q when done"; +static constant char w_proto[] = + "Waiting for data"; public char *prproto[3]; -public char *eqproto = e_proto; +public char constant *eqproto = e_proto; +public char constant *hproto = h_proto; +public char constant *wproto = w_proto; -static char message[250]; +static char message[PROMPT_SIZE]; static char *mp; /* @@ -77,53 +70,82 @@ public void init_prompt() { - prproto[0] = save(s_proto); + prproto[0] = save(ismore ? more_proto : s_proto); prproto[1] = save(m_proto); prproto[2] = save(M_proto); eqproto = save(e_proto); + hproto = save(h_proto); + wproto = save(w_proto); } /* - * Set the message pointer to the end of the message string. + * Append a string to the end of the message. */ static void -setmp() +ap_str(s) + char *s; { - while (*mp != '\0') - mp++; + int len; + + len = strlen(s); + if (mp + len >= message + PROMPT_SIZE) + len = message + PROMPT_SIZE - mp - 1; + strncpy(mp, s, len); + mp += len; + *mp = '\0'; } /* + * Append a character to the end of the message. + */ + static void +ap_char(c) + char c; +{ + char buf[2]; + + buf[0] = c; + buf[1] = '\0'; + ap_str(buf); +} + +/* * Append a POSITION (as a decimal integer) to the end of the message. */ static void ap_pos(pos) POSITION pos; { - snprintf(mp, message + sizeof message - mp, "%qd", pos); - setmp(); + char buf[INT_STRLEN_BOUND(pos) + 2]; + + postoa(pos, buf, sizeof(buf)); + ap_str(buf); } /* - * Append an integer to the end of the message. + * Append a line number to the end of the message. */ - static void -ap_int(n) - int n; + static void +ap_linenum(linenum) + LINENUM linenum; { - snprintf(mp, message + sizeof message - mp, "%d", n); - setmp(); + char buf[INT_STRLEN_BOUND(linenum) + 2]; + + linenumtoa(linenum, buf, sizeof(buf)); + ap_str(buf); } /* - * Append a string to the end of the message. + * Append an integer to the end of the message. */ static void -ap_str(s) - char *s; +ap_int(num) + int num; { - strtcpy(mp, s, (unsigned int)(&message[sizeof(message)] - mp)); - setmp(); + char buf[INT_STRLEN_BOUND(num) + 2]; + + inttoa(num, buf, sizeof(buf)); + ap_str(buf); } /* @@ -132,8 +154,7 @@ static void ap_quest() { - if (mp < message + sizeof message - 1) - *mp++ = '?'; + ap_str("?"); } /* @@ -164,31 +185,53 @@ char c; int where; { + POSITION len; + switch (c) { case 'a': /* Anything in the message yet? */ return (mp > message); case 'b': /* Current byte offset known? */ return (curr_byte(where) != NULL_POSITION); + case 'c': + return (hshift != 0); case 'e': /* At end of file? */ return (hit_eof); case 'f': /* Filename known? */ return (strcmp(get_filename(curr_ifile), "-") != 0); case 'l': /* Line number known? */ + case 'd': /* Same as l */ return (linenums); case 'L': /* Final line number known? */ + case 'D': /* Same as L */ return (linenums && ch_length() != NULL_POSITION); case 'm': /* More than one file? */ +#if TAGS + return (ntags() ? (ntags() > 1) : (nifile() > 1)); +#else return (nifile() > 1); +#endif case 'n': /* First prompt in a new file? */ +#if TAGS + return (ntags() ? 1 : new_file); +#else return (new_file); - case 'p': /* Percent into file known? */ +#endif + case 'p': /* Percent into file (bytes) known? */ return (curr_byte(where) != NULL_POSITION && ch_length() > 0); + case 'P': /* Percent into file (lines) known? */ + return (currline(where) != 0 && + (len = ch_length()) > 0 && + find_linenum(len) != 0); case 's': /* Size of file known? */ case 'B': return (ch_length() != NULL_POSITION); case 'x': /* Is there a "next" file? */ +#if TAGS + if (ntags()) + return (0); +#endif return (next_ifile(curr_ifile) != NULL_IFILE); } return (0); @@ -202,13 +245,16 @@ * usually by appending something to the message being built. */ static void -protochar(c, where) +protochar(c, where, iseditproto) int c; int where; + int iseditproto; { POSITION pos; POSITION len; int n; + LINENUM linenum; + LINENUM last_linenum; IFILE h; switch (c) @@ -220,6 +266,24 @@ else ap_quest(); break; + case 'c': + ap_int(hshift); + break; + case 'd': /* Current page number */ + linenum = currline(where); + if (linenum > 0 && sc_height > 1) + ap_linenum(((linenum - 1) / (sc_height - 1)) + 1); + else + ap_quest(); + break; + case 'D': /* Last page number */ + len = ch_length(); + if (len == NULL_POSITION || len == ch_zero() || + (linenum = find_linenum(len)) <= 0) + ap_quest(); + else + ap_linenum(((linenum - 1) / (sc_height - 1)) + 1); + break; #if EDITOR case 'E': /* Editor name */ ap_str(editor); @@ -229,27 +293,38 @@ ap_str(get_filename(curr_ifile)); break; case 'i': /* Index into list of files */ - ap_int(get_index(curr_ifile)); +#if TAGS + if (ntags()) + ap_int(curr_tag()); + else +#endif + ap_int(get_index(curr_ifile)); break; case 'l': /* Current line number */ - n = currline(where); - if (n != 0) - ap_int(n); + linenum = currline(where); + if (linenum != 0) + ap_linenum(linenum); else ap_quest(); break; case 'L': /* Final line number */ len = ch_length(); if (len == NULL_POSITION || len == ch_zero() || - (n = find_linenum(len)) <= 0) + (linenum = find_linenum(len)) <= 0) ap_quest(); else - ap_int(n-1); + ap_linenum(linenum-1); break; case 'm': /* Number of files */ - ap_int(nifile()); +#if TAGS + n = ntags(); + if (n) + ap_int(n); + else +#endif + ap_int(nifile()); break; - case 'p': /* Percent into file */ + case 'p': /* Percent into file (bytes) */ pos = curr_byte(where); len = ch_length(); if (pos != NULL_POSITION && len > 0) @@ -257,6 +332,15 @@ else ap_quest(); break; + case 'P': /* Percent into file (lines) */ + linenum = currline(where); + if (linenum == 0 || + (len = ch_length()) == NULL_POSITION || len == ch_zero() || + (last_linenum = find_linenum(len)) <= 0) + ap_quest(); + else + ap_int(percentage(linenum, last_linenum)); + break; case 's': /* Size of file */ case 'B': len = ch_length(); @@ -269,6 +353,14 @@ while (mp > message && mp[-1] == ' ') mp--; break; + case 'T': /* Type of list */ +#if TAGS + if (ntags()) + ap_str("tag"); + else +#endif + ap_str("file"); + break; case 'x': /* Name of next file */ h = next_ifile(curr_ifile); if (h != NULL_IFILE) @@ -288,9 +380,9 @@ */ static char * skipcond(p) - char *p; + register char *p; { - int iflevel; + register int iflevel; /* * We came in here after processing a ? or :, @@ -341,6 +433,9 @@ /*NOTREACHED*/ } +/* + * Decode a char that represents a position on the screen. + */ static char * wherechar(p, wp) char *p; @@ -348,7 +443,7 @@ { switch (*p) { - case 'b': case 'l': case 'p': + case 'b': case 'd': case 'l': case 'p': case 'P': switch (*++p) { case 't': *wp = TOP; break; @@ -370,8 +465,8 @@ char *proto; int maxwidth; { - char *p; - int c; + register char *p; + register int c; int where; mp = message; @@ -384,17 +479,18 @@ switch (*p) { default: /* Just put the character in the message */ - *mp++ = *p; + ap_char(*p); break; case '\\': /* Backslash escapes the next character */ p++; - *mp++ = *p; + ap_char(*p); break; case '?': /* Conditional (IF) */ if ((c = *++p) == '\0') --p; else { + where = 0; p = wherechar(p, &where); if (!cond(c, where)) p = skipcond(p); @@ -410,17 +506,22 @@ --p; else { + where = 0; p = wherechar(p, &where); - protochar(c, where); + protochar(c, where, +#if EDITOR + (proto == editproto)); +#else + 0); +#endif + } break; } } - new_file = 0; if (mp == message) return (NULL); - *mp = '\0'; if (maxwidth > 0 && mp >= message + maxwidth) { /* @@ -450,5 +551,20 @@ public char * pr_string() { - return (pr_expand(prproto[pr_type], sc_width-so_s_width-so_e_width-2)); + char *prompt; + + prompt = pr_expand((ch_getflags() & CH_HELPFILE) ? + hproto : prproto[pr_type], + sc_width-so_s_width-so_e_width-2); + new_file = 0; + return (prompt); +} + +/* + * Return a message suitable for printing while waiting in the F command. + */ + public char * +wait_message() +{ + return (pr_expand(wproto, sc_width-so_s_width-so_e_width-2)); }