1a5f0fb15SPaul Saab /* 2*c77c4889SXin LI * Copyright (C) 1984-2024 Mark Nudelman 3a5f0fb15SPaul Saab * 4a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 5a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 6a5f0fb15SPaul Saab * 796e55cc7SXin LI * For more information, see the README file. 8a5f0fb15SPaul Saab */ 9a5f0fb15SPaul Saab 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab /* 12a5f0fb15SPaul Saab * Prompting and other messages. 13a5f0fb15SPaul Saab * There are three flavors of prompts, SHORT, MEDIUM and LONG, 14a5f0fb15SPaul Saab * selected by the -m/-M options. 15a5f0fb15SPaul Saab * There is also the "equals message", printed by the = command. 16a5f0fb15SPaul Saab * A prompt is a message composed of various pieces, such as the 17a5f0fb15SPaul Saab * name of the file being viewed, the percentage into the file, etc. 18a5f0fb15SPaul Saab */ 19a5f0fb15SPaul Saab 20a5f0fb15SPaul Saab #include "less.h" 21a5f0fb15SPaul Saab #include "position.h" 22a5f0fb15SPaul Saab 23a5f0fb15SPaul Saab extern int pr_type; 24*c77c4889SXin LI extern lbool new_file; 25a5f0fb15SPaul Saab extern int linenums; 26a5f0fb15SPaul Saab extern int hshift; 27a5f0fb15SPaul Saab extern int sc_height; 28a5f0fb15SPaul Saab extern int jump_sline; 29720c436cSXin LI extern int less_is_more; 3095270f73SXin LI extern int header_lines; 31*c77c4889SXin LI extern int utf_mode; 32a5f0fb15SPaul Saab extern IFILE curr_ifile; 33*c77c4889SXin LI #if OSC8_LINK 34*c77c4889SXin LI extern char *osc8_path; 35*c77c4889SXin LI #endif 36a5f0fb15SPaul Saab #if EDITOR 37*c77c4889SXin LI extern constant char *editor; 38*c77c4889SXin LI extern constant char *editproto; 39a5f0fb15SPaul Saab #endif 40a5f0fb15SPaul Saab 41a5f0fb15SPaul Saab /* 42a5f0fb15SPaul Saab * Prototypes for the three flavors of prompts. 43a5f0fb15SPaul Saab * These strings are expanded by pr_expand(). 44a5f0fb15SPaul Saab */ 45a5f0fb15SPaul Saab static constant char s_proto[] = 468fd4165cSPaul Saab "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x..%t"; 47a5f0fb15SPaul Saab static constant char m_proto[] = 488fd4165cSPaul Saab "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t"; 49a5f0fb15SPaul Saab static constant char M_proto[] = 508fd4165cSPaul Saab "?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"; 51a5f0fb15SPaul Saab static constant char e_proto[] = 528fd4165cSPaul Saab "?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t"; 53a5f0fb15SPaul Saab static constant char h_proto[] = 54a5f0fb15SPaul Saab "HELP -- ?eEND -- Press g to see it again:Press RETURN for more., or q when done"; 558fd4165cSPaul Saab static constant char w_proto[] = 568fd4165cSPaul Saab "Waiting for data"; 57720c436cSXin LI static constant char more_proto[] = 58720c436cSXin LI "--More--(?eEND ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t)"; 59a5f0fb15SPaul Saab 60a5f0fb15SPaul Saab public char *prproto[3]; 61a5f0fb15SPaul Saab public char constant *eqproto = e_proto; 62a5f0fb15SPaul Saab public char constant *hproto = h_proto; 638fd4165cSPaul Saab public char constant *wproto = w_proto; 64a5f0fb15SPaul Saab 65a5f0fb15SPaul Saab static char message[PROMPT_SIZE]; 66a5f0fb15SPaul Saab static char *mp; 67a5f0fb15SPaul Saab 68a5f0fb15SPaul Saab /* 69a5f0fb15SPaul Saab * Initialize the prompt prototype strings. 70a5f0fb15SPaul Saab */ 71d713e089SXin LI public void init_prompt(void) 72a5f0fb15SPaul Saab { 73a5f0fb15SPaul Saab prproto[0] = save(s_proto); 74720c436cSXin LI prproto[1] = save(less_is_more ? more_proto : m_proto); 75a5f0fb15SPaul Saab prproto[2] = save(M_proto); 76a5f0fb15SPaul Saab eqproto = save(e_proto); 77a5f0fb15SPaul Saab hproto = save(h_proto); 788fd4165cSPaul Saab wproto = save(w_proto); 79a5f0fb15SPaul Saab } 80a5f0fb15SPaul Saab 81a5f0fb15SPaul Saab /* 82a5f0fb15SPaul Saab * Append a string to the end of the message. 83*c77c4889SXin LI * nprt means the character *may* be nonprintable 84*c77c4889SXin LI * and should be converted to printable form. 85a5f0fb15SPaul Saab */ 86*c77c4889SXin LI static void ap_estr(constant char *s, lbool nprt) 87a5f0fb15SPaul Saab { 88*c77c4889SXin LI constant char *es = s + strlen(s); 89*c77c4889SXin LI while (*s != '\0') 90*c77c4889SXin LI { 91*c77c4889SXin LI LWCHAR ch = step_charc(&s, +1, es); 92*c77c4889SXin LI constant char *ps; 93*c77c4889SXin LI char ubuf[MAX_UTF_CHAR_LEN+1]; 94*c77c4889SXin LI size_t plen; 95a5f0fb15SPaul Saab 96*c77c4889SXin LI if (nprt) 97*c77c4889SXin LI { 98*c77c4889SXin LI ps = utf_mode ? prutfchar(ch) : prchar(ch); 99*c77c4889SXin LI } else 100*c77c4889SXin LI { 101*c77c4889SXin LI char *up = ubuf; 102*c77c4889SXin LI put_wchar(&up, ch); 103*c77c4889SXin LI *up = '\0'; 104*c77c4889SXin LI ps = ubuf; 105*c77c4889SXin LI } 106*c77c4889SXin LI plen = strlen(ps); 107*c77c4889SXin LI if (mp + plen >= message + PROMPT_SIZE) 108*c77c4889SXin LI break; 109*c77c4889SXin LI strcpy(mp, ps); 110*c77c4889SXin LI mp += plen; 111*c77c4889SXin LI } 112a5f0fb15SPaul Saab *mp = '\0'; 113a5f0fb15SPaul Saab } 114a5f0fb15SPaul Saab 115*c77c4889SXin LI static void ap_str(constant char *s) 116*c77c4889SXin LI { 117*c77c4889SXin LI ap_estr(s, FALSE); 118*c77c4889SXin LI } 119*c77c4889SXin LI 120a5f0fb15SPaul Saab /* 121a5f0fb15SPaul Saab * Append a character to the end of the message. 122a5f0fb15SPaul Saab */ 123d713e089SXin LI static void ap_char(char c) 124a5f0fb15SPaul Saab { 125*c77c4889SXin LI if (mp + 1 >= message + PROMPT_SIZE) 126*c77c4889SXin LI return; 127*c77c4889SXin LI *mp++ = c; 128*c77c4889SXin LI *mp = '\0'; 129a5f0fb15SPaul Saab } 130a5f0fb15SPaul Saab 131a5f0fb15SPaul Saab /* 132a5f0fb15SPaul Saab * Append a POSITION (as a decimal integer) to the end of the message. 133a5f0fb15SPaul Saab */ 134d713e089SXin LI static void ap_pos(POSITION pos) 135a5f0fb15SPaul Saab { 1361ede1615STim J. Robbins char buf[INT_STRLEN_BOUND(pos) + 2]; 137a5f0fb15SPaul Saab 138d713e089SXin LI postoa(pos, buf, 10); 1391ede1615STim J. Robbins ap_str(buf); 1401ede1615STim J. Robbins } 1411ede1615STim J. Robbins 1421ede1615STim J. Robbins /* 1431ede1615STim J. Robbins * Append a line number to the end of the message. 1441ede1615STim J. Robbins */ 145d713e089SXin LI static void ap_linenum(LINENUM linenum) 1461ede1615STim J. Robbins { 1471ede1615STim J. Robbins char buf[INT_STRLEN_BOUND(linenum) + 2]; 1481ede1615STim J. Robbins 149d713e089SXin LI linenumtoa(linenum, buf, 10); 1501ede1615STim J. Robbins ap_str(buf); 151a5f0fb15SPaul Saab } 152a5f0fb15SPaul Saab 153a5f0fb15SPaul Saab /* 154a5f0fb15SPaul Saab * Append an integer to the end of the message. 155a5f0fb15SPaul Saab */ 156d713e089SXin LI static void ap_int(int num) 157a5f0fb15SPaul Saab { 1581ede1615STim J. Robbins char buf[INT_STRLEN_BOUND(num) + 2]; 159a5f0fb15SPaul Saab 160d713e089SXin LI inttoa(num, buf, 10); 161a5f0fb15SPaul Saab ap_str(buf); 162a5f0fb15SPaul Saab } 163a5f0fb15SPaul Saab 164a5f0fb15SPaul Saab /* 165a5f0fb15SPaul Saab * Append a question mark to the end of the message. 166a5f0fb15SPaul Saab */ 167d713e089SXin LI static void ap_quest(void) 168a5f0fb15SPaul Saab { 169a5f0fb15SPaul Saab ap_str("?"); 170a5f0fb15SPaul Saab } 171a5f0fb15SPaul Saab 172a5f0fb15SPaul Saab /* 173a5f0fb15SPaul Saab * Return the "current" byte offset in the file. 174a5f0fb15SPaul Saab */ 175d713e089SXin LI static POSITION curr_byte(int where) 176a5f0fb15SPaul Saab { 177a5f0fb15SPaul Saab POSITION pos; 178a5f0fb15SPaul Saab 179a5f0fb15SPaul Saab pos = position(where); 18089dd99dcSXin LI while (pos == NULL_POSITION && where >= 0 && where < sc_height-1) 181a5f0fb15SPaul Saab pos = position(++where); 182a5f0fb15SPaul Saab if (pos == NULL_POSITION) 183a5f0fb15SPaul Saab pos = ch_length(); 184a5f0fb15SPaul Saab return (pos); 185a5f0fb15SPaul Saab } 186a5f0fb15SPaul Saab 187a5f0fb15SPaul Saab /* 188a5f0fb15SPaul Saab * Return the value of a prototype conditional. 189a5f0fb15SPaul Saab * A prototype string may include conditionals which consist of a 190a5f0fb15SPaul Saab * question mark followed by a single letter. 191a5f0fb15SPaul Saab * Here we decode that letter and return the appropriate boolean value. 192a5f0fb15SPaul Saab */ 193*c77c4889SXin LI static lbool cond(char c, int where) 194a5f0fb15SPaul Saab { 195a5f0fb15SPaul Saab POSITION len; 196a5f0fb15SPaul Saab 197a5f0fb15SPaul Saab switch (c) 198a5f0fb15SPaul Saab { 199a5f0fb15SPaul Saab case 'a': /* Anything in the message yet? */ 200a5f0fb15SPaul Saab return (mp > message); 201a5f0fb15SPaul Saab case 'b': /* Current byte offset known? */ 202a5f0fb15SPaul Saab return (curr_byte(where) != NULL_POSITION); 203a5f0fb15SPaul Saab case 'c': 204a5f0fb15SPaul Saab return (hshift != 0); 205a5f0fb15SPaul Saab case 'e': /* At end of file? */ 2067374caaaSXin LI return (eof_displayed()); 207a5f0fb15SPaul Saab case 'f': /* Filename known? */ 208b7780dbeSXin LI case 'g': 209a5f0fb15SPaul Saab return (strcmp(get_filename(curr_ifile), "-") != 0); 210a5f0fb15SPaul Saab case 'l': /* Line number known? */ 211a5f0fb15SPaul Saab case 'd': /* Same as l */ 212b7780dbeSXin LI if (!linenums) 213*c77c4889SXin LI return FALSE; 214b7780dbeSXin LI return (currline(where) != 0); 215a5f0fb15SPaul Saab case 'L': /* Final line number known? */ 21689dd99dcSXin LI case 'D': /* Final page number known? */ 217a5f0fb15SPaul Saab return (linenums && ch_length() != NULL_POSITION); 218a5f0fb15SPaul Saab case 'm': /* More than one file? */ 2191ede1615STim J. Robbins #if TAGS 2208fd4165cSPaul Saab return (ntags() ? (ntags() > 1) : (nifile() > 1)); 2211ede1615STim J. Robbins #else 2221ede1615STim J. Robbins return (nifile() > 1); 2231ede1615STim J. Robbins #endif 224a5f0fb15SPaul Saab case 'n': /* First prompt in a new file? */ 2251ede1615STim J. Robbins #if TAGS 226*c77c4889SXin LI return (ntags() ? TRUE : new_file ? TRUE : FALSE); 2271ede1615STim J. Robbins #else 228*c77c4889SXin LI return (new_file ? TRUE : FALSE); 2291ede1615STim J. Robbins #endif 230a5f0fb15SPaul Saab case 'p': /* Percent into file (bytes) known? */ 231*c77c4889SXin LI return (curr_byte(where) != NULL_POSITION && ch_length() > 0); 232a5f0fb15SPaul Saab case 'P': /* Percent into file (lines) known? */ 233a5f0fb15SPaul Saab return (currline(where) != 0 && 234a5f0fb15SPaul Saab (len = ch_length()) > 0 && 235a5f0fb15SPaul Saab find_linenum(len) != 0); 236a5f0fb15SPaul Saab case 's': /* Size of file known? */ 237a5f0fb15SPaul Saab case 'B': 238a5f0fb15SPaul Saab return (ch_length() != NULL_POSITION); 239a5f0fb15SPaul Saab case 'x': /* Is there a "next" file? */ 2401ede1615STim J. Robbins #if TAGS 2418fd4165cSPaul Saab if (ntags()) 242*c77c4889SXin LI return (FALSE); 2431ede1615STim J. Robbins #endif 244a5f0fb15SPaul Saab return (next_ifile(curr_ifile) != NULL_IFILE); 245a5f0fb15SPaul Saab } 246*c77c4889SXin LI return (FALSE); 247a5f0fb15SPaul Saab } 248a5f0fb15SPaul Saab 249a5f0fb15SPaul Saab /* 250a5f0fb15SPaul Saab * Decode a "percent" prototype character. 251a5f0fb15SPaul Saab * A prototype string may include various "percent" escapes; 252a5f0fb15SPaul Saab * that is, a percent sign followed by a single letter. 253a5f0fb15SPaul Saab * Here we decode that letter and take the appropriate action, 254a5f0fb15SPaul Saab * usually by appending something to the message being built. 255a5f0fb15SPaul Saab */ 256*c77c4889SXin LI static void protochar(char c, int where) 257a5f0fb15SPaul Saab { 258a5f0fb15SPaul Saab POSITION pos; 259a5f0fb15SPaul Saab POSITION len; 260a5f0fb15SPaul Saab int n; 2611ede1615STim J. Robbins LINENUM linenum; 2621ede1615STim J. Robbins LINENUM last_linenum; 263a5f0fb15SPaul Saab IFILE h; 264b7780dbeSXin LI char *s; 265a5f0fb15SPaul Saab 26689dd99dcSXin LI #undef PAGE_NUM 26795270f73SXin LI #define PAGE_NUM(linenum) ((((linenum) - 1) / (sc_height - header_lines - 1)) + 1) 26889dd99dcSXin LI 269a5f0fb15SPaul Saab switch (c) 270a5f0fb15SPaul Saab { 271a5f0fb15SPaul Saab case 'b': /* Current byte offset */ 272a5f0fb15SPaul Saab pos = curr_byte(where); 273a5f0fb15SPaul Saab if (pos != NULL_POSITION) 274a5f0fb15SPaul Saab ap_pos(pos); 275a5f0fb15SPaul Saab else 276a5f0fb15SPaul Saab ap_quest(); 277a5f0fb15SPaul Saab break; 278a5f0fb15SPaul Saab case 'c': 279a5f0fb15SPaul Saab ap_int(hshift); 280a5f0fb15SPaul Saab break; 281a5f0fb15SPaul Saab case 'd': /* Current page number */ 2821ede1615STim J. Robbins linenum = currline(where); 28395270f73SXin LI if (linenum > 0 && sc_height > header_lines + 1) 28489dd99dcSXin LI ap_linenum(PAGE_NUM(linenum)); 285a5f0fb15SPaul Saab else 286a5f0fb15SPaul Saab ap_quest(); 287a5f0fb15SPaul Saab break; 28889dd99dcSXin LI case 'D': /* Final page number */ 28989dd99dcSXin LI /* Find the page number of the last byte in the file (len-1). */ 290a5f0fb15SPaul Saab len = ch_length(); 29189dd99dcSXin LI if (len == NULL_POSITION) 29289dd99dcSXin LI ap_quest(); 29389dd99dcSXin LI else if (len == 0) 29489dd99dcSXin LI /* An empty file has no pages. */ 29589dd99dcSXin LI ap_linenum(0); 29689dd99dcSXin LI else 29789dd99dcSXin LI { 29889dd99dcSXin LI linenum = find_linenum(len - 1); 29989dd99dcSXin LI if (linenum <= 0) 300a5f0fb15SPaul Saab ap_quest(); 301a5f0fb15SPaul Saab else 30289dd99dcSXin LI ap_linenum(PAGE_NUM(linenum)); 30389dd99dcSXin LI } 304a5f0fb15SPaul Saab break; 305a5f0fb15SPaul Saab #if EDITOR 306a5f0fb15SPaul Saab case 'E': /* Editor name */ 307a5f0fb15SPaul Saab ap_str(editor); 308a5f0fb15SPaul Saab break; 309a5f0fb15SPaul Saab #endif 310a5f0fb15SPaul Saab case 'f': /* File name */ 311*c77c4889SXin LI ap_estr(get_filename(curr_ifile), TRUE); 312a5f0fb15SPaul Saab break; 31333096f16SXin LI case 'F': /* Last component of file name */ 314*c77c4889SXin LI ap_estr(last_component(get_filename(curr_ifile)), TRUE); 31533096f16SXin LI break; 316b7780dbeSXin LI case 'g': /* Shell-escaped file name */ 317b7780dbeSXin LI s = shell_quote(get_filename(curr_ifile)); 318b7780dbeSXin LI ap_str(s); 319b7780dbeSXin LI free(s); 320b7780dbeSXin LI break; 321a5f0fb15SPaul Saab case 'i': /* Index into list of files */ 3221ede1615STim J. Robbins #if TAGS 3238fd4165cSPaul Saab if (ntags()) 3248fd4165cSPaul Saab ap_int(curr_tag()); 3258fd4165cSPaul Saab else 3261ede1615STim J. Robbins #endif 327a5f0fb15SPaul Saab ap_int(get_index(curr_ifile)); 328a5f0fb15SPaul Saab break; 329a5f0fb15SPaul Saab case 'l': /* Current line number */ 3301ede1615STim J. Robbins linenum = currline(where); 3311ede1615STim J. Robbins if (linenum != 0) 33295270f73SXin LI ap_linenum(vlinenum(linenum)); 333a5f0fb15SPaul Saab else 334a5f0fb15SPaul Saab ap_quest(); 335a5f0fb15SPaul Saab break; 336a5f0fb15SPaul Saab case 'L': /* Final line number */ 337a5f0fb15SPaul Saab len = ch_length(); 338a5f0fb15SPaul Saab if (len == NULL_POSITION || len == ch_zero() || 3391ede1615STim J. Robbins (linenum = find_linenum(len)) <= 0) 340a5f0fb15SPaul Saab ap_quest(); 341a5f0fb15SPaul Saab else 34295270f73SXin LI ap_linenum(vlinenum(linenum-1)); 343a5f0fb15SPaul Saab break; 344a5f0fb15SPaul Saab case 'm': /* Number of files */ 3451ede1615STim J. Robbins #if TAGS 3468fd4165cSPaul Saab n = ntags(); 3478fd4165cSPaul Saab if (n) 3488fd4165cSPaul Saab ap_int(n); 3498fd4165cSPaul Saab else 3501ede1615STim J. Robbins #endif 351a5f0fb15SPaul Saab ap_int(nifile()); 352a5f0fb15SPaul Saab break; 353*c77c4889SXin LI case 'o': /* path (URI without protocol) of selected OSC8 link */ 354*c77c4889SXin LI #if OSC8_LINK 355*c77c4889SXin LI if (osc8_path != NULL) 356*c77c4889SXin LI ap_str(osc8_path); 357*c77c4889SXin LI else 358*c77c4889SXin LI #endif 359*c77c4889SXin LI ap_quest(); 360*c77c4889SXin LI break; 361a5f0fb15SPaul Saab case 'p': /* Percent into file (bytes) */ 362a5f0fb15SPaul Saab pos = curr_byte(where); 363a5f0fb15SPaul Saab len = ch_length(); 364a5f0fb15SPaul Saab if (pos != NULL_POSITION && len > 0) 365a5f0fb15SPaul Saab ap_int(percentage(pos,len)); 366a5f0fb15SPaul Saab else 367a5f0fb15SPaul Saab ap_quest(); 368a5f0fb15SPaul Saab break; 369a5f0fb15SPaul Saab case 'P': /* Percent into file (lines) */ 3701ede1615STim J. Robbins linenum = currline(where); 3711ede1615STim J. Robbins if (linenum == 0 || 372a5f0fb15SPaul Saab (len = ch_length()) == NULL_POSITION || len == ch_zero() || 3731ede1615STim J. Robbins (last_linenum = find_linenum(len)) <= 0) 374a5f0fb15SPaul Saab ap_quest(); 375a5f0fb15SPaul Saab else 3761ede1615STim J. Robbins ap_int(percentage(linenum, last_linenum)); 377a5f0fb15SPaul Saab break; 378a5f0fb15SPaul Saab case 's': /* Size of file */ 379a5f0fb15SPaul Saab case 'B': 380a5f0fb15SPaul Saab len = ch_length(); 381a5f0fb15SPaul Saab if (len != NULL_POSITION) 382a5f0fb15SPaul Saab ap_pos(len); 383a5f0fb15SPaul Saab else 384a5f0fb15SPaul Saab ap_quest(); 385a5f0fb15SPaul Saab break; 386a5f0fb15SPaul Saab case 't': /* Truncate trailing spaces in the message */ 387a5f0fb15SPaul Saab while (mp > message && mp[-1] == ' ') 388a5f0fb15SPaul Saab mp--; 38933096f16SXin LI *mp = '\0'; 390a5f0fb15SPaul Saab break; 3918fd4165cSPaul Saab case 'T': /* Type of list */ 3921ede1615STim J. Robbins #if TAGS 3938fd4165cSPaul Saab if (ntags()) 3948fd4165cSPaul Saab ap_str("tag"); 3958fd4165cSPaul Saab else 3961ede1615STim J. Robbins #endif 3978fd4165cSPaul Saab ap_str("file"); 3988fd4165cSPaul Saab break; 399a5f0fb15SPaul Saab case 'x': /* Name of next file */ 400a5f0fb15SPaul Saab h = next_ifile(curr_ifile); 401a5f0fb15SPaul Saab if (h != NULL_IFILE) 4021ede1615STim J. Robbins ap_str(get_filename(h)); 4031ede1615STim J. Robbins else 404a5f0fb15SPaul Saab ap_quest(); 405a5f0fb15SPaul Saab break; 406a5f0fb15SPaul Saab } 407a5f0fb15SPaul Saab } 408a5f0fb15SPaul Saab 409a5f0fb15SPaul Saab /* 410a5f0fb15SPaul Saab * Skip a false conditional. 411a5f0fb15SPaul Saab * When a false condition is found (either a false IF or the ELSE part 412a5f0fb15SPaul Saab * of a true IF), this routine scans the prototype string to decide 413a5f0fb15SPaul Saab * where to resume parsing the string. 414a5f0fb15SPaul Saab * We must keep track of nested IFs and skip them properly. 415a5f0fb15SPaul Saab */ 416d713e089SXin LI static constant char * skipcond(constant char *p) 417a5f0fb15SPaul Saab { 4181ea31627SRobert Watson int iflevel; 419a5f0fb15SPaul Saab 420a5f0fb15SPaul Saab /* 421a5f0fb15SPaul Saab * We came in here after processing a ? or :, 422a5f0fb15SPaul Saab * so we start nested one level deep. 423a5f0fb15SPaul Saab */ 424a5f0fb15SPaul Saab iflevel = 1; 425a5f0fb15SPaul Saab 426a5f0fb15SPaul Saab for (;;) switch (*++p) 427a5f0fb15SPaul Saab { 428a5f0fb15SPaul Saab case '?': 429a5f0fb15SPaul Saab /* 430a5f0fb15SPaul Saab * Start of a nested IF. 431a5f0fb15SPaul Saab */ 432a5f0fb15SPaul Saab iflevel++; 433a5f0fb15SPaul Saab break; 434a5f0fb15SPaul Saab case ':': 435a5f0fb15SPaul Saab /* 436a5f0fb15SPaul Saab * Else. 437a5f0fb15SPaul Saab * If this matches the IF we came in here with, 438a5f0fb15SPaul Saab * then we're done. 439a5f0fb15SPaul Saab */ 440a5f0fb15SPaul Saab if (iflevel == 1) 441a5f0fb15SPaul Saab return (p); 442a5f0fb15SPaul Saab break; 443a5f0fb15SPaul Saab case '.': 444a5f0fb15SPaul Saab /* 445a5f0fb15SPaul Saab * Endif. 446a5f0fb15SPaul Saab * If this matches the IF we came in here with, 447a5f0fb15SPaul Saab * then we're done. 448a5f0fb15SPaul Saab */ 449a5f0fb15SPaul Saab if (--iflevel == 0) 450a5f0fb15SPaul Saab return (p); 451a5f0fb15SPaul Saab break; 452a5f0fb15SPaul Saab case '\\': 453a5f0fb15SPaul Saab /* 454a5f0fb15SPaul Saab * Backslash escapes the next character. 455a5f0fb15SPaul Saab */ 456d713e089SXin LI if (p[1] != '\0') 457a5f0fb15SPaul Saab ++p; 458a5f0fb15SPaul Saab break; 459a5f0fb15SPaul Saab case '\0': 460a5f0fb15SPaul Saab /* 461a5f0fb15SPaul Saab * Whoops. Hit end of string. 462a5f0fb15SPaul Saab * This is a malformed conditional, but just treat it 463a5f0fb15SPaul Saab * as if all active conditionals ends here. 464a5f0fb15SPaul Saab */ 465a5f0fb15SPaul Saab return (p-1); 466a5f0fb15SPaul Saab } 467a5f0fb15SPaul Saab /*NOTREACHED*/ 468a5f0fb15SPaul Saab } 469a5f0fb15SPaul Saab 470a5f0fb15SPaul Saab /* 471a5f0fb15SPaul Saab * Decode a char that represents a position on the screen. 472a5f0fb15SPaul Saab */ 473d713e089SXin LI static constant char * wherechar(char constant *p, int *wp) 474a5f0fb15SPaul Saab { 475a5f0fb15SPaul Saab switch (*p) 476a5f0fb15SPaul Saab { 477a5f0fb15SPaul Saab case 'b': case 'd': case 'l': case 'p': case 'P': 478a5f0fb15SPaul Saab switch (*++p) 479a5f0fb15SPaul Saab { 480a5f0fb15SPaul Saab case 't': *wp = TOP; break; 481a5f0fb15SPaul Saab case 'm': *wp = MIDDLE; break; 482a5f0fb15SPaul Saab case 'b': *wp = BOTTOM; break; 483a5f0fb15SPaul Saab case 'B': *wp = BOTTOM_PLUS_ONE; break; 484b2ea2440SXin LI case 'j': *wp = sindex_from_sline(jump_sline); break; 485a5f0fb15SPaul Saab default: *wp = TOP; p--; break; 486a5f0fb15SPaul Saab } 487a5f0fb15SPaul Saab } 488a5f0fb15SPaul Saab return (p); 489a5f0fb15SPaul Saab } 490a5f0fb15SPaul Saab 491a5f0fb15SPaul Saab /* 492a5f0fb15SPaul Saab * Construct a message based on a prototype string. 493a5f0fb15SPaul Saab */ 494*c77c4889SXin LI public constant char * pr_expand(constant char *proto) 495a5f0fb15SPaul Saab { 4961ea31627SRobert Watson constant char *p; 497*c77c4889SXin LI char c; 498a5f0fb15SPaul Saab int where; 499a5f0fb15SPaul Saab 500a5f0fb15SPaul Saab mp = message; 501a5f0fb15SPaul Saab 502a5f0fb15SPaul Saab if (*proto == '\0') 503a5f0fb15SPaul Saab return (""); 504a5f0fb15SPaul Saab 505a5f0fb15SPaul Saab for (p = proto; *p != '\0'; p++) 506a5f0fb15SPaul Saab { 507a5f0fb15SPaul Saab switch (*p) 508a5f0fb15SPaul Saab { 509a5f0fb15SPaul Saab default: /* Just put the character in the message */ 510a5f0fb15SPaul Saab ap_char(*p); 511a5f0fb15SPaul Saab break; 512a5f0fb15SPaul Saab case '\\': /* Backslash escapes the next character */ 513d713e089SXin LI if (p[1] != '\0') 514d713e089SXin LI ap_char(*++p); 515a5f0fb15SPaul Saab break; 516a5f0fb15SPaul Saab case '?': /* Conditional (IF) */ 517a5f0fb15SPaul Saab if ((c = *++p) == '\0') 518a5f0fb15SPaul Saab --p; 519a5f0fb15SPaul Saab else 520a5f0fb15SPaul Saab { 521a5f0fb15SPaul Saab where = 0; 522a5f0fb15SPaul Saab p = wherechar(p, &where); 523a5f0fb15SPaul Saab if (!cond(c, where)) 524a5f0fb15SPaul Saab p = skipcond(p); 525a5f0fb15SPaul Saab } 526a5f0fb15SPaul Saab break; 527a5f0fb15SPaul Saab case ':': /* ELSE */ 528a5f0fb15SPaul Saab p = skipcond(p); 529a5f0fb15SPaul Saab break; 530a5f0fb15SPaul Saab case '.': /* ENDIF */ 531a5f0fb15SPaul Saab break; 532a5f0fb15SPaul Saab case '%': /* Percent escape */ 533a5f0fb15SPaul Saab if ((c = *++p) == '\0') 534a5f0fb15SPaul Saab --p; 535a5f0fb15SPaul Saab else 536a5f0fb15SPaul Saab { 537a5f0fb15SPaul Saab where = 0; 538a5f0fb15SPaul Saab p = wherechar(p, &where); 539*c77c4889SXin LI protochar(c, where); 540a5f0fb15SPaul Saab } 541a5f0fb15SPaul Saab break; 542a5f0fb15SPaul Saab } 543a5f0fb15SPaul Saab } 544a5f0fb15SPaul Saab 545a5f0fb15SPaul Saab if (mp == message) 54689dd99dcSXin LI return (""); 547a5f0fb15SPaul Saab return (message); 548a5f0fb15SPaul Saab } 549a5f0fb15SPaul Saab 550a5f0fb15SPaul Saab /* 551a5f0fb15SPaul Saab * Return a message suitable for printing by the "=" command. 552a5f0fb15SPaul Saab */ 553*c77c4889SXin LI public constant char * eq_message(void) 554a5f0fb15SPaul Saab { 55595270f73SXin LI return (pr_expand(eqproto)); 556a5f0fb15SPaul Saab } 557a5f0fb15SPaul Saab 558a5f0fb15SPaul Saab /* 559a5f0fb15SPaul Saab * Return a prompt. 560a5f0fb15SPaul Saab * This depends on the prompt type (SHORT, MEDIUM, LONG), etc. 561a5f0fb15SPaul Saab * If we can't come up with an appropriate prompt, return NULL 562a5f0fb15SPaul Saab * and the caller will prompt with a colon. 563a5f0fb15SPaul Saab */ 564*c77c4889SXin LI public constant char * pr_string(void) 565a5f0fb15SPaul Saab { 566*c77c4889SXin LI constant char *prompt; 567720c436cSXin LI int type; 5688fd4165cSPaul Saab 569720c436cSXin LI type = (!less_is_more) ? pr_type : pr_type ? 0 : 1; 5708fd4165cSPaul Saab prompt = pr_expand((ch_getflags() & CH_HELPFILE) ? 57195270f73SXin LI hproto : prproto[type]); 572*c77c4889SXin LI new_file = FALSE; 5738fd4165cSPaul Saab return (prompt); 5748fd4165cSPaul Saab } 5758fd4165cSPaul Saab 5768fd4165cSPaul Saab /* 5778fd4165cSPaul Saab * Return a message suitable for printing while waiting in the F command. 5788fd4165cSPaul Saab */ 579*c77c4889SXin LI public constant char * wait_message(void) 5808fd4165cSPaul Saab { 58195270f73SXin LI return (pr_expand(wproto)); 582a5f0fb15SPaul Saab } 583