2 * Prompting and other messages.
3 * There are three flavors of prompts, SHORT, MEDIUM and LONG,
4 * selected by the -m/-M options.
5 * There is also the "equals message", printed by the = command.
6 * A prompt is a message composed of various pieces, such as the
7 * name of the file being viewed, the percentage into the file, etc.
17 extern int so_s_width, so_e_width;
20 extern int jump_sline;
21 extern IFILE curr_ifile;
27 * Prototypes for the three flavors of prompts.
28 * These strings are expanded by pr_expand().
30 static char s_proto[] =
31 "?n?f%f .?m(file %i of %m) ..?e(END) ?x- Next\\: %x..%t";
32 static char m_proto[] =
33 "?n?f%f .?m(file %i of %m) ..?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t";
34 static char M_proto[] =
35 "?f%f .?n?m(file %i of %m) ..?ltline %lt?L/%L. :byte %bB?s/%s. .?e(END) ?x- Next\\: %x.:?pB%pB\\%..%t";
36 static char e_proto[] =
37 "?f%f .?m(file %i of %m) .?ltline %lt?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t";
39 public char *prproto[3];
40 public char *eqproto = e_proto;
42 static char message[250];
46 * Initialize the prompt prototype strings.
51 prproto[0] = save(s_proto);
52 prproto[1] = save(m_proto);
53 prproto[2] = save(M_proto);
54 eqproto = save(e_proto);
58 * Set the message pointer to the end of the message string.
68 * Append a POSITION (as a decimal integer) to the end of the message.
74 sprintf(mp, "%ld", (long)pos);
79 * Append an integer to the end of the message.
90 * Append a string to the end of the message.
96 strtcpy(mp, s, (unsigned int)(&message[sizeof(message)] - mp));
101 * Append a question mark to the end of the message.
110 * Return the "current" byte offset in the file.
118 pos = position(where);
119 while (pos == NULL_POSITION && where >= 0 && where < sc_height)
120 pos = position(++where);
121 if (pos == NULL_POSITION)
127 * Return the value of a prototype conditional.
128 * A prototype string may include conditionals which consist of a
129 * question mark followed by a single letter.
130 * Here we decode that letter and return the appropriate boolean value.
139 case 'a': /* Anything in the message yet? */
140 return (mp > message);
141 case 'b': /* Current byte offset known? */
142 return (curr_byte(where) != NULL_POSITION);
143 case 'e': /* At end of file? */
145 case 'f': /* Filename known? */
146 return (strcmp(get_filename(curr_ifile), "-") != 0);
147 case 'l': /* Line number known? */
149 case 'L': /* Final line number known? */
150 return (linenums && ch_length() != NULL_POSITION);
151 case 'm': /* More than one file? */
152 return (nifile() > 1);
153 case 'n': /* First prompt in a new file? */
155 case 'p': /* Percent into file known? */
156 return (curr_byte(where) != NULL_POSITION &&
158 case 's': /* Size of file known? */
160 return (ch_length() != NULL_POSITION);
161 case 'x': /* Is there a "next" file? */
162 return (next_ifile(curr_ifile) != NULL_IFILE);
168 * Decode a "percent" prototype character.
169 * A prototype string may include various "percent" escapes;
170 * that is, a percent sign followed by a single letter.
171 * Here we decode that letter and take the appropriate action,
172 * usually by appending something to the message being built.
186 case 'b': /* Current byte offset */
187 pos = curr_byte(where);
188 if (pos != NULL_POSITION)
194 case 'E': /* Editor name */
198 case 'f': /* File name */
199 ap_str(get_filename(curr_ifile));
201 case 'i': /* Index into list of files */
202 ap_int(get_index(curr_ifile));
204 case 'l': /* Current line number */
211 case 'L': /* Final line number */
213 if (len == NULL_POSITION || len == ch_zero() ||
214 (n = find_linenum(len)) <= 0)
219 case 'm': /* Number of files */
222 case 'p': /* Percent into file */
223 pos = curr_byte(where);
225 if (pos != NULL_POSITION && len > 0)
227 * {{ This calculation may overflow! }}
229 ap_int((int)(100*pos / len));
233 case 's': /* Size of file */
236 if (len != NULL_POSITION)
241 case 't': /* Truncate trailing spaces in the message */
242 while (mp > message && mp[-1] == ' ')
245 case 'x': /* Name of next file */
246 h = next_ifile(curr_ifile);
248 ap_str(get_filename(h));
256 * Skip a false conditional.
257 * When a false condition is found (either a false IF or the ELSE part
258 * of a true IF), this routine scans the prototype string to decide
259 * where to resume parsing the string.
260 * We must keep track of nested IFs and skip them properly.
266 register int iflevel;
269 * We came in here after processing a ? or :,
270 * so we start nested one level deep.
274 for (;;) switch (*++p)
278 * Start of a nested IF.
285 * If this matches the IF we came in here with,
294 * If this matches the IF we came in here with,
302 * Backslash escapes the next character.
308 * Whoops. Hit end of string.
309 * This is a malformed conditional, but just treat it
310 * as if all active conditionals ends here.
324 case 'b': case 'l': case 'p':
327 case 't': *wp = TOP; break;
328 case 'm': *wp = MIDDLE; break;
329 case 'b': *wp = BOTTOM; break;
330 case 'B': *wp = BOTTOM_PLUS_ONE; break;
331 case 'j': *wp = adjsline(jump_sline); break;
332 default: *wp = TOP; p--; break;
339 * Construct a message based on a prototype string.
342 pr_expand(proto, maxwidth)
355 for (p = proto; *p != '\0'; p++)
359 default: /* Just put the character in the message */
362 case '\\': /* Backslash escapes the next character */
366 case '?': /* Conditional (IF) */
367 if ((c = *++p) == '\0')
371 p = wherechar(p, &where);
379 case '.': /* ENDIF */
381 case '%': /* Percent escape */
382 if ((c = *++p) == '\0')
386 p = wherechar(p, &where);
397 if (maxwidth > 0 && mp >= message + maxwidth)
400 * Message is too long.
401 * Return just the final portion of it.
403 return (mp - maxwidth);
409 * Return a message suitable for printing by the "=" command.
414 return (pr_expand(eqproto, 0));
419 * This depends on the prompt type (SHORT, MEDIUM, LONG), etc.
420 * If we can't come up with an appropriate prompt, return NULL
421 * and the caller will prompt with a colon.
426 return (pr_expand(prproto[pr_type], sc_width-so_s_width-so_e_width-2));