prompt.c revision 240121
11556Srgrimes/* $FreeBSD: stable/9/contrib/less/prompt.c 240121 2012-09-04 23:24:00Z delphij $ */
21556Srgrimes/*
31556Srgrimes * Copyright (C) 1984-2012  Mark Nudelman
41556Srgrimes *
51556Srgrimes * You may distribute under the terms of either the GNU General Public
61556Srgrimes * License or the Less License, as specified in the README file.
71556Srgrimes *
81556Srgrimes * For more information, see the README file.
91556Srgrimes */
101556Srgrimes
111556Srgrimes
121556Srgrimes/*
131556Srgrimes * Prompting and other messages.
141556Srgrimes * There are three flavors of prompts, SHORT, MEDIUM and LONG,
151556Srgrimes * selected by the -m/-M options.
161556Srgrimes * There is also the "equals message", printed by the = command.
171556Srgrimes * A prompt is a message composed of various pieces, such as the
181556Srgrimes * name of the file being viewed, the percentage into the file, etc.
191556Srgrimes */
201556Srgrimes
211556Srgrimes#include "less.h"
221556Srgrimes#include "position.h"
231556Srgrimes
241556Srgrimesextern int pr_type;
251556Srgrimesextern int new_file;
261556Srgrimesextern int sc_width;
271556Srgrimesextern int so_s_width, so_e_width;
281556Srgrimesextern int linenums;
291556Srgrimesextern int hshift;
301556Srgrimesextern int sc_height;
311556Srgrimesextern int jump_sline;
321556Srgrimesextern int less_is_more;
331556Srgrimesextern IFILE curr_ifile;
3436150Scharnier#if EDITOR
3536150Scharnierextern char *editor;
3636150Scharnierextern char *editproto;
371556Srgrimes#endif
3899110Sobrien
3999110Sobrien/*
401556Srgrimes * Prototypes for the three flavors of prompts.
41213775Sjhb * These strings are expanded by pr_expand().
42213775Sjhb */
43213775Sjhbstatic constant char s_proto[] =
44213775Sjhb  "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x..%t";
45213775Sjhbstatic constant char m_proto[] =
46213775Sjhb  "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t";
4717987Speterstatic constant char M_proto[] =
48213775Sjhb  "?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";
4917987Speterstatic constant char e_proto[] =
50213925Sjilles  "?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t";
51213775Sjhbstatic constant char h_proto[] =
5217987Speter  "HELP -- ?eEND -- Press g to see it again:Press RETURN for more., or q when done";
5317987Speterstatic constant char w_proto[] =
541556Srgrimes  "Waiting for data";
551556Srgrimesstatic constant char more_proto[] =
5617987Speter  "--More--(?eEND ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t)";
571556Srgrimes
581556Srgrimespublic char *prproto[3];
5917987Speterpublic char constant *eqproto = e_proto;
6017987Speterpublic char constant *hproto = h_proto;
611556Srgrimespublic char constant *wproto = w_proto;
621556Srgrimes
631556Srgrimesstatic char message[PROMPT_SIZE];
641556Srgrimesstatic char *mp;
651556Srgrimes
661556Srgrimes/*
671556Srgrimes * Initialize the prompt prototype strings.
681556Srgrimes */
691556Srgrimes	public void
701556Srgrimesinit_prompt()
711556Srgrimes{
721556Srgrimes	prproto[0] = save(s_proto);
731556Srgrimes	prproto[1] = save(less_is_more ? more_proto : m_proto);
741556Srgrimes	prproto[2] = save(M_proto);
75213760Sobrien	eqproto = save(e_proto);
76213760Sobrien	hproto = save(h_proto);
7728346Ssteve	wproto = save(w_proto);
78209600Sjilles}
791556Srgrimes
80213760Sobrien/*
81213760Sobrien * Append a string to the end of the message.
821556Srgrimes */
8338536Scracauer	static void
8438950Scracauerap_str(s)
8538536Scracauer	char *s;
8699762Stjr{
871556Srgrimes	int len;
8820425Ssteve
89213811Sobrien	len = strlen(s);
9020425Ssteve	if (mp + len >= message + PROMPT_SIZE)
91213811Sobrien		len = message + PROMPT_SIZE - mp - 1;
92213811Sobrien	strncpy(mp, s, len);
93213811Sobrien	mp += len;
94213811Sobrien	*mp = '\0';
95213811Sobrien}
96213811Sobrien
97213811Sobrien/*
9897659Stjr * Append a character to the end of the message.
99213811Sobrien */
100213811Sobrien	static void
101213811Sobrienap_char(c)
10297659Stjr	char c;
103213811Sobrien{
1041556Srgrimes	char buf[2];
1051556Srgrimes
1061556Srgrimes	buf[0] = c;
1071556Srgrimes	buf[1] = '\0';
1081556Srgrimes	ap_str(buf);
1091556Srgrimes}
1101556Srgrimes
1111556Srgrimes/*
11220425Ssteve * Append a POSITION (as a decimal integer) to the end of the message.
1131556Srgrimes */
11490111Simp	static void
11517987Speterap_pos(pos)
11699762Stjr	POSITION pos;
1171556Srgrimes{
1181556Srgrimes	char buf[INT_STRLEN_BOUND(pos) + 2];
1191556Srgrimes
1201556Srgrimes	postoa(pos, buf);
12199762Stjr	ap_str(buf);
12299762Stjr}
12399762Stjr
12499762Stjr/*
12599762Stjr * Append a line number to the end of the message.
12699762Stjr */
127109927Stjr 	static void
12899762Stjrap_linenum(linenum)
12999762Stjr	LINENUM linenum;
130109927Stjr{
131109927Stjr	char buf[INT_STRLEN_BOUND(linenum) + 2];
132109927Stjr
133109927Stjr	linenumtoa(linenum, buf);
134109927Stjr	ap_str(buf);
135109927Stjr}
136109927Stjr
137109927Stjr/*
138109927Stjr * Append an integer to the end of the message.
139109927Stjr */
140109927Stjr	static void
141109927Stjrap_int(num)
142109927Stjr	int num;
143103223Snectar{
14499762Stjr	char buf[INT_STRLEN_BOUND(num) + 2];
14599762Stjr
14699762Stjr	inttoa(num, buf);
14799762Stjr	ap_str(buf);
1481556Srgrimes}
14999762Stjr
15020425Ssteve/*
151199629Sjilles * Append a question mark to the end of the message.
1521556Srgrimes */
1531556Srgrimes	static void
1541556Srgrimesap_quest()
1551556Srgrimes{
15617987Speter	ap_str("?");
15717987Speter}
15899762Stjr
1591556Srgrimes/*
1601556Srgrimes * Return the "current" byte offset in the file.
1611556Srgrimes */
1621556Srgrimes	static POSITION
1631556Srgrimescurr_byte(where)
1641556Srgrimes	int where;
16517987Speter{
16699762Stjr	POSITION pos;
1671556Srgrimes
16817987Speter	pos = position(where);
16999762Stjr	while (pos == NULL_POSITION && where >= 0 && where < sc_height-1)
17099762Stjr		pos = position(++where);
17199762Stjr	if (pos == NULL_POSITION)
1721556Srgrimes		pos = ch_length();
1731556Srgrimes	return (pos);
1741556Srgrimes}
1751556Srgrimes
1761556Srgrimes/*
1771556Srgrimes * Return the value of a prototype conditional.
17820425Ssteve * A prototype string may include conditionals which consist of a
1791556Srgrimes * question mark followed by a single letter.
1801556Srgrimes * Here we decode that letter and return the appropriate boolean value.
1811556Srgrimes */
18228346Ssteve	static int
18317987Spetercond(c, where)
1841556Srgrimes	char c;
1851556Srgrimes	int where;
1861556Srgrimes{
187209600Sjilles	POSITION len;
1881556Srgrimes
1891556Srgrimes	switch (c)
1901556Srgrimes	{
1911556Srgrimes	case 'a':	/* Anything in the message yet? */
1921556Srgrimes		return (mp > message);
1931556Srgrimes	case 'b':	/* Current byte offset known? */
1941556Srgrimes		return (curr_byte(where) != NULL_POSITION);
1951556Srgrimes	case 'c':
1961556Srgrimes		return (hshift != 0);
1971556Srgrimes	case 'e':	/* At end of file? */
19817987Speter		return (eof_displayed());
19990111Simp	case 'f':	/* Filename known? */
20017987Speter		return (strcmp(get_filename(curr_ifile), "-") != 0);
2011556Srgrimes	case 'l':	/* Line number known? */
202100308Stjr	case 'd':	/* Same as l */
2031556Srgrimes		return (linenums);
2041556Srgrimes	case 'L':	/* Final line number known? */
2051556Srgrimes	case 'D':	/* Final page number known? */
2061556Srgrimes		return (linenums && ch_length() != NULL_POSITION);
2071556Srgrimes	case 'm':	/* More than one file? */
20896933Stjr#if TAGS
20996933Stjr		return (ntags() ? (ntags() > 1) : (nifile() > 1));
21096933Stjr#else
2111556Srgrimes		return (nifile() > 1);
21299762Stjr#endif
2131556Srgrimes	case 'n':	/* First prompt in a new file? */
214100305Stjr#if TAGS
2151556Srgrimes		return (ntags() ? 1 : new_file);
21645916Scracauer#else
2171556Srgrimes		return (new_file);
2181556Srgrimes#endif
2191556Srgrimes	case 'p':	/* Percent into file (bytes) known? */
2201556Srgrimes		return (curr_byte(where) != NULL_POSITION &&
2211556Srgrimes				ch_length() > 0);
22217987Speter	case 'P':	/* Percent into file (lines) known? */
22390111Simp		return (currline(where) != 0 &&
22417987Speter				(len = ch_length()) > 0 &&
22596933Stjr				find_linenum(len) != 0);
2261556Srgrimes	case 's':	/* Size of file known? */
2271556Srgrimes	case 'B':
2281556Srgrimes		return (ch_length() != NULL_POSITION);
2291556Srgrimes	case 'x':	/* Is there a "next" file? */
2301556Srgrimes#if TAGS
2311556Srgrimes		if (ntags())
23296933Stjr			return (0);
23396933Stjr#endif
2341556Srgrimes		return (next_ifile(curr_ifile) != NULL_IFILE);
235100305Stjr	}
236104275Smux	return (0);
23796933Stjr}
23896933Stjr
23996933Stjr/*
2401556Srgrimes * Decode a "percent" prototype character.
2411556Srgrimes * A prototype string may include various "percent" escapes;
2421556Srgrimes * that is, a percent sign followed by a single letter.
2431556Srgrimes * Here we decode that letter and take the appropriate action,
2441556Srgrimes * usually by appending something to the message being built.
245213811Sobrien */
24690111Simp	static void
24717987Speterprotochar(c, where, iseditproto)
2481556Srgrimes	int c;
2491556Srgrimes	int where;
2501556Srgrimes	int iseditproto;
2511556Srgrimes{
2521556Srgrimes	POSITION pos;
25397660Stjr	POSITION len;
2541556Srgrimes	int n;
2551556Srgrimes	LINENUM linenum;
2561556Srgrimes	LINENUM last_linenum;
25726104Ssteve	IFILE h;
2581556Srgrimes
2591556Srgrimes#undef  PAGE_NUM
2601556Srgrimes#define PAGE_NUM(linenum)  ((((linenum) - 1) / (sc_height - 1)) + 1)
2611556Srgrimes
2621556Srgrimes	switch (c)
2631556Srgrimes	{
2641556Srgrimes	case 'b':	/* Current byte offset */
2651556Srgrimes		pos = curr_byte(where);
2661556Srgrimes		if (pos != NULL_POSITION)
2671556Srgrimes			ap_pos(pos);
26897669Stjr		else
26917987Speter			ap_quest();
27097669Stjr		break;
271163085Sstefanf	case 'c':
27297669Stjr		ap_int(hshift);
27397669Stjr		break;
274100663Stjr	case 'd':	/* Current page number */
275163085Sstefanf		linenum = currline(where);
276163085Sstefanf		if (linenum > 0 && sc_height > 1)
27797669Stjr			ap_linenum(PAGE_NUM(linenum));
27897669Stjr		else
279163085Sstefanf			ap_quest();
28097669Stjr		break;
281163085Sstefanf	case 'D':	/* Final page number */
282163085Sstefanf		/* Find the page number of the last byte in the file (len-1). */
283163085Sstefanf		len = ch_length();
28497669Stjr		if (len == NULL_POSITION)
285163085Sstefanf			ap_quest();
28697669Stjr		else if (len == 0)
28797669Stjr			/* An empty file has no pages. */
28897669Stjr			ap_linenum(0);
28997669Stjr		else
29097669Stjr		{
29197669Stjr			linenum = find_linenum(len - 1);
29297669Stjr			if (linenum <= 0)
29397669Stjr				ap_quest();
29497669Stjr			else
29597669Stjr				ap_linenum(PAGE_NUM(linenum));
296163085Sstefanf		}
29797669Stjr		break;
29897669Stjr#if EDITOR
299163085Sstefanf	case 'E':	/* Editor name */
30097669Stjr		ap_str(editor);
30197669Stjr		break;
3021556Srgrimes#endif
3031556Srgrimes	case 'f':	/* File name */
304213811Sobrien		ap_str(get_filename(curr_ifile));
305163085Sstefanf		break;
30697663Stjr	case 'F':	/* Last component of file name */
30797663Stjr		ap_str(last_component(get_filename(curr_ifile)));
30897663Stjr		break;
30997669Stjr	case 'i':	/* Index into list of files */
31097669Stjr#if TAGS
311163085Sstefanf		if (ntags())
31297669Stjr			ap_int(curr_tag());
3131556Srgrimes		else
314163085Sstefanf#endif
31597663Stjr			ap_int(get_index(curr_ifile));
31697669Stjr		break;
31797669Stjr	case 'l':	/* Current line number */
31897669Stjr		linenum = currline(where);
31997669Stjr		if (linenum != 0)
32097669Stjr			ap_linenum(linenum);
32197669Stjr		else
32297669Stjr			ap_quest();
32397669Stjr		break;
32497663Stjr	case 'L':	/* Final line number */
325163085Sstefanf		len = ch_length();
326163085Sstefanf		if (len == NULL_POSITION || len == ch_zero() ||
327163085Sstefanf		    (linenum = find_linenum(len)) <= 0)
328163085Sstefanf			ap_quest();
32997669Stjr		else
33097669Stjr			ap_linenum(linenum-1);
331163085Sstefanf		break;
33297669Stjr	case 'm':	/* Number of files */
33397822Stjr#if TAGS
33497822Stjr		n = ntags();
33597819Stjr		if (n)
33697669Stjr			ap_int(n);
33797819Stjr		else
33897669Stjr#endif
33997669Stjr			ap_int(nifile());
34097669Stjr		break;
34197663Stjr	case 'p':	/* Percent into file (bytes) */
34297669Stjr		pos = curr_byte(where);
34397663Stjr		len = ch_length();
34497816Stjr		if (pos != NULL_POSITION && len > 0)
34597663Stjr			ap_int(percentage(pos,len));
34697663Stjr		else
347163085Sstefanf			ap_quest();
348100308Stjr		break;
34997669Stjr	case 'P':	/* Percent into file (lines) */
35097669Stjr		linenum = currline(where);
35197669Stjr		if (linenum == 0 ||
35297663Stjr		    (len = ch_length()) == NULL_POSITION || len == ch_zero() ||
35397819Stjr		    (last_linenum = find_linenum(len)) <= 0)
35497819Stjr			ap_quest();
35597819Stjr		else
35697669Stjr			ap_int(percentage(linenum, last_linenum));
35797663Stjr		break;
35897820Stjr	case 's':	/* Size of file */
35997820Stjr	case 'B':
36097820Stjr		len = ch_length();
36197820Stjr		if (len != NULL_POSITION)
36297820Stjr			ap_pos(len);
36397663Stjr		else
36497663Stjr			ap_quest();
365155301Sschweikh		break;
36697663Stjr	case 't':	/* Truncate trailing spaces in the message */
36797663Stjr		while (mp > message && mp[-1] == ' ')
36897663Stjr			mp--;
36997663Stjr		*mp = '\0';
370125155Snjl		break;
37197663Stjr	case 'T':	/* Type of list */
37297663Stjr#if TAGS
37397663Stjr		if (ntags())
37497663Stjr			ap_str("tag");
37597663Stjr		else
37697663Stjr#endif
37797663Stjr			ap_str("file");
37897663Stjr		break;
37997663Stjr	case 'x':	/* Name of next file */
38097663Stjr		h = next_ifile(curr_ifile);
38197663Stjr		if (h != NULL_IFILE)
38297663Stjr			ap_str(get_filename(h));
38397663Stjr		else
38497663Stjr			ap_quest();
38597669Stjr		break;
38697663Stjr	}
38797663Stjr}
38897663Stjr
38997663Stjr/*
3901556Srgrimes * Skip a false conditional.
3911556Srgrimes * When a false condition is found (either a false IF or the ELSE part
3921556Srgrimes * of a true IF), this routine scans the prototype string to decide
3931556Srgrimes * where to resume parsing the string.
3941556Srgrimes * We must keep track of nested IFs and skip them properly.
3951556Srgrimes */
3961556Srgrimes	static constant char *
3971556Srgrimesskipcond(p)
3981556Srgrimes	register constant char *p;
3991556Srgrimes{
400163085Sstefanf	register int iflevel;
40117987Speter
4021556Srgrimes	/*
4031556Srgrimes	 * We came in here after processing a ? or :,
4041556Srgrimes	 * so we start nested one level deep.
4051556Srgrimes	 */
406208489Sjilles	iflevel = 1;
4071556Srgrimes
4081556Srgrimes	for (;;) switch (*++p)
4091556Srgrimes	{
4101556Srgrimes	case '?':
4111556Srgrimes		/*
4121556Srgrimes		 * Start of a nested IF.
4131556Srgrimes		 */
4141556Srgrimes		iflevel++;
4151556Srgrimes		break;
416163085Sstefanf	case ':':
4171556Srgrimes		/*
418209600Sjilles		 * Else.
419209600Sjilles		 * If this matches the IF we came in here with,
420209600Sjilles		 * then we're done.
421209600Sjilles		 */
422209600Sjilles		if (iflevel == 1)
4231556Srgrimes			return (p);
4241556Srgrimes		break;
4251556Srgrimes	case '.':
4261556Srgrimes		/*
4271556Srgrimes		 * Endif.
4281556Srgrimes		 * If this matches the IF we came in here with,
4291556Srgrimes		 * then we're done.
4301556Srgrimes		 */
4311556Srgrimes		if (--iflevel == 0)
4321556Srgrimes			return (p);
433213811Sobrien		break;
43490111Simp	case '\\':
43590111Simp		/*
4361556Srgrimes		 * Backslash escapes the next character.
4371556Srgrimes		 */
4381556Srgrimes		++p;
4391556Srgrimes		break;
440209600Sjilles	case '\0':
441209600Sjilles		/*
4421556Srgrimes		 * Whoops.  Hit end of string.
4431556Srgrimes		 * This is a malformed conditional, but just treat it
4441556Srgrimes		 * as if all active conditionals ends here.
4451556Srgrimes		 */
4461556Srgrimes		return (p-1);
4471556Srgrimes	}
4481556Srgrimes	/*NOTREACHED*/
4491556Srgrimes}
45097659Stjr
4511556Srgrimes/*
4521556Srgrimes * Decode a char that represents a position on the screen.
4531556Srgrimes */
4541556Srgrimes	static constant char *
4551556Srgrimeswherechar(p, wp)
4561556Srgrimes	char constant *p;
4571556Srgrimes	int *wp;
45890111Simp{
45917987Speter	switch (*p)
4601556Srgrimes	{
46126104Ssteve	case 'b': case 'd': case 'l': case 'p': case 'P':
4621556Srgrimes		switch (*++p)
4631556Srgrimes		{
4641556Srgrimes		case 't':   *wp = TOP;			break;
4651556Srgrimes		case 'm':   *wp = MIDDLE;		break;
4661556Srgrimes		case 'b':   *wp = BOTTOM;		break;
4671556Srgrimes		case 'B':   *wp = BOTTOM_PLUS_ONE;	break;
4681556Srgrimes		case 'j':   *wp = adjsline(jump_sline);	break;
46938536Scracauer		default:    *wp = TOP;  p--;		break;
47038536Scracauer		}
47138536Scracauer	}
47238536Scracauer	return (p);
47338536Scracauer}
47438536Scracauer
47538521Scracauer/*
47638536Scracauer * Construct a message based on a prototype string.
4771556Srgrimes */
4781556Srgrimes	public char *
4791556Srgrimespr_expand(proto, maxwidth)
48026104Ssteve	constant char *proto;
48126104Ssteve	int maxwidth;
4821556Srgrimes{
48326104Ssteve	register constant char *p;
48426104Ssteve	register int c;
4851556Srgrimes	int where;
4861556Srgrimes
48726104Ssteve	mp = message;
488209600Sjilles
4891556Srgrimes	if (*proto == '\0')
490209600Sjilles		return ("");
491209600Sjilles
492209600Sjilles	for (p = proto;  *p != '\0';  p++)
493209600Sjilles	{
494209600Sjilles		switch (*p)
49538536Scracauer		{
49626104Ssteve		default:	/* Just put the character in the message */
4971556Srgrimes			ap_char(*p);
4981556Srgrimes			break;
499209600Sjilles		case '\\':	/* Backslash escapes the next character */
500209600Sjilles			p++;
501209600Sjilles			ap_char(*p);
502209600Sjilles			break;
503209600Sjilles		case '?':	/* Conditional (IF) */
504209600Sjilles			if ((c = *++p) == '\0')
505209600Sjilles				--p;
506209600Sjilles			else
507209600Sjilles			{
508209600Sjilles				where = 0;
5091556Srgrimes				p = wherechar(p, &where);
5101556Srgrimes				if (!cond(c, where))
51138536Scracauer					p = skipcond(p);
5121556Srgrimes			}
5131556Srgrimes			break;
5141556Srgrimes		case ':':	/* ELSE */
5151556Srgrimes			p = skipcond(p);
5161556Srgrimes			break;
5171556Srgrimes		case '.':	/* ENDIF */
51838521Scracauer			break;
51938521Scracauer		case '%':	/* Percent escape */
52038521Scracauer			if ((c = *++p) == '\0')
52138521Scracauer				--p;
5221556Srgrimes			else
5231556Srgrimes			{
5241556Srgrimes				where = 0;
5251556Srgrimes				p = wherechar(p, &where);
52617987Speter				protochar(c, where,
52790111Simp#if EDITOR
52817987Speter					(proto == editproto));
5291556Srgrimes#else
5301556Srgrimes					0);
5311556Srgrimes#endif
5321556Srgrimes
5331556Srgrimes			}
534100308Stjr			break;
5351556Srgrimes		}
5361556Srgrimes	}
5371556Srgrimes
5381556Srgrimes	if (mp == message)
5391556Srgrimes		return ("");
5401556Srgrimes	if (maxwidth > 0 && mp >= message + maxwidth)
5411556Srgrimes	{
5421556Srgrimes		/*
5431556Srgrimes		 * Message is too long.
5441556Srgrimes		 * Return just the final portion of it.
5451556Srgrimes		 */
546213811Sobrien		return (mp - maxwidth);
54790111Simp	}
54890111Simp	return (message);
5491556Srgrimes}
55097688Stjr
551100308Stjr/*
5521556Srgrimes * Return a message suitable for printing by the "=" command.
5531556Srgrimes */
5541556Srgrimes	public char *
5551556Srgrimeseq_message()
55697659Stjr{
5571556Srgrimes	return (pr_expand(eqproto, 0));
55897659Stjr}
5591556Srgrimes
5601556Srgrimes/*
5611556Srgrimes * Return a prompt.
5621556Srgrimes * This depends on the prompt type (SHORT, MEDIUM, LONG), etc.
5631556Srgrimes * If we can't come up with an appropriate prompt, return NULL
5641556Srgrimes * and the caller will prompt with a colon.
5651556Srgrimes */
5661556Srgrimes	public char *
5671556Srgrimespr_string()
5681556Srgrimes{
5691556Srgrimes	char *prompt;
5701556Srgrimes	int type;
57197688Stjr
57297688Stjr	type = (!less_is_more) ? pr_type : pr_type ? 0 : 1;
57397688Stjr	prompt = pr_expand((ch_getflags() & CH_HELPFILE) ?
57497688Stjr				hproto : prproto[type],
57597688Stjr			sc_width-so_s_width-so_e_width-2);
57697688Stjr	new_file = 0;
57797688Stjr	return (prompt);
5781556Srgrimes}
57997688Stjr
58097688Stjr/*
58197688Stjr * Return a message suitable for printing while waiting in the F command.
58297688Stjr */
58397688Stjr	public char *
58497688Stjrwait_message()
58597688Stjr{
58697688Stjr	return (pr_expand(wproto, sc_width-so_s_width-so_e_width-2));
58797688Stjr}
58897688Stjr