int prompt(void) { off_t len, pos; /* * if nothing is displayed yet, display starting from line 1; * if search string provided, go there instead. */ if (position(TOP) == NULL_POSITION) { if (forw_line((off_t)0) == NULL_POSITION) return(0); if (!firstsearch || !search(1, firstsearch, 1, 1)) jump_back(1); } else if (screen_trashed) repaint(); /* if no -e flag and we've hit EOF on the last file, quit. */ if ((!quit_at_eof || short_file) && hit_eof && curr_ac + 1 >= ac) quit(); /* select the proper prompt and display it. */ lower_left(); clear_eol(); if (longprompt) { so_enter(); printf("%s:", current_name); if (!ispipe) printf(" file %d/%d", curr_ac + 1, ac); if (linenums) printf(" line %d", currline(BOTTOM)); if ((pos = position(BOTTOM)) != NULL_POSITION) { printf(" byte %qd", pos); if (!ispipe && (len = ch_length())) printf("/%qd pct %qd%%", len, ((100 * pos) / len)); } so_exit(); longprompt = 0; } else { so_enter(); printf("%s", current_name); if (hit_eof) if (next_name) printf(": END (next file: %s)", next_name); else printf(": END"); else if (!ispipe && (pos = position(BOTTOM)) != NULL_POSITION && (len = ch_length())) printf(" (%qd%%)", ((100 * pos) / len)); so_exit(); } return(1); }
/* * Forward forever, or until a highlighted line appears. */ static int forw_loop(int until_hilite) { off_t curr_len; if (ch_getflags() & CH_HELPFILE) return (A_NOACTION); cmd_exec(); jump_forw(); curr_len = ch_length(); highest_hilite = until_hilite ? curr_len : -1; ignore_eoi = 1; while (!sigs) { if (until_hilite && highest_hilite > curr_len) { ring_bell(); break; } make_display(); forward(1, 0, 0); } ignore_eoi = 0; ch_set_eof(); /* * This gets us back in "F mode" after processing * a non-abort signal (e.g. window-change). */ if (sigs && !ABORT_SIGS()) return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER); return (A_NOACTION); }
/* * Append the byte offset into the current file. */ static void ap_byte() { POSITION pos, len; pos = position(BOTTOM_PLUS_ONE); if (pos == NULL_POSITION) pos = ch_length(); if (pos != NULL_POSITION) { sprintf(mp, " byte %ld", (long)pos); setmp(); len = ch_length(); if (len > 0) { sprintf(mp, "/%ld", (long)len); setmp(); } } }
/* * Return the value of a prototype conditional. * A prototype string may include conditionals which consist of a * question mark followed by a single letter. * Here we decode that letter and return the appropriate boolean value. */ static int cond(char c, int where) { off_t len; switch (c) { case 'a': /* Anything in the message yet? */ return (*message != '\0'); case 'b': /* Current byte offset known? */ return (curr_byte(where) != -1); case 'c': return (hshift != 0); case 'e': /* At end of file? */ return (eof_displayed()); 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': /* Final page number known? */ return (linenums && ch_length() != -1); case 'm': /* More than one file? */ return (ntags() ? (ntags() > 1) : (nifile() > 1)); case 'n': /* First prompt in a new file? */ return (ntags() ? 1 : new_file); case 'p': /* Percent into file (bytes) known? */ return (curr_byte(where) != -1 && 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() != -1); case 'x': /* Is there a "next" file? */ if (ntags()) return (0); return (next_ifile(curr_ifile) != NULL); } return (0); }
/* * Return the "current" byte offset in the file. */ static off_t curr_byte(int where) { off_t pos; pos = position(where); while (pos == -1 && where >= 0 && where < sc_height-1) pos = position(++where); if (pos == -1) pos = ch_length(); return (pos); }
/* * Append the percentage into the current file. * If we cannot find the percentage and must_print is true, * use the byte offset. */ static void ap_percent(int must_print) { POSITION pos,len; pos = position(BOTTOM_PLUS_ONE); len = ch_length(); if (len > 0 && pos != NULL_POSITION) { sprintf(mp, " (%ld%%)", (100 * (long)pos) / len); setmp(); } else if (must_print) ap_byte(); }
/* * Check to see if the end of file is currently "displayed". */ eof_check() { off_t pos; if (sigs) return; /* * If the bottom line is empty, we are at EOF. * If the bottom line ends at the file length, * we must be just at EOF. */ pos = position(BOTTOM_PLUS_ONE); if (pos == NULL_POSITION || pos == ch_length()) hit_eof++; }
/* * Check to see if the end of file is currently "displayed". */ void eof_check() /*###72 [cc] conflicting types for `eof_check'%%%*/ { off_t pos; if (sigs) return; /* * If the bottom line is empty, we are at EOF. * If the bottom line ends at the file length, * we must be just at EOF. */ pos = position(BOTTOM_PLUS_ONE); if (pos == NULL_POSITION || pos == ch_length()) hit_eof++; }
/* * Decode a "percent" prototype character. * A prototype string may include various "percent" escapes; * that is, a percent sign followed by a single letter. * Here we decode that letter and take the appropriate action, * usually by appending something to the message being built. */ static void protochar(int c, int where) { off_t pos; off_t len; int n; off_t linenum; off_t last_linenum; IFILE h; #undef PAGE_NUM #define PAGE_NUM(linenum) ((((linenum) - 1) / (sc_height - 1)) + 1) switch (c) { case 'b': /* Current byte offset */ pos = curr_byte(where); if (pos != -1) ap_pos(pos); 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_pos(PAGE_NUM(linenum)); else ap_quest(); break; case 'D': /* Final page number */ /* Find the page number of the last byte in the file (len-1). */ len = ch_length(); if (len == -1) { ap_quest(); } else if (len == 0) { /* An empty file has no pages. */ ap_pos(0); } else { linenum = find_linenum(len - 1); if (linenum <= 0) ap_quest(); else ap_pos(PAGE_NUM(linenum)); } break; case 'E': /* Editor name */ ap_str(editor); break; case 'f': /* File name */ ap_str(get_filename(curr_ifile)); break; case 'F': /* Last component of file name */ ap_str(last_component(get_filename(curr_ifile))); break; case 'i': /* Index into list of files */ if (ntags()) ap_int(curr_tag()); else ap_int(get_index(curr_ifile)); break; case 'l': /* Current line number */ linenum = currline(where); if (linenum != 0) ap_pos(linenum); else ap_quest(); break; case 'L': /* Final line number */ len = ch_length(); if (len == -1 || len == ch_zero() || (linenum = find_linenum(len)) <= 0) ap_quest(); else ap_pos(linenum-1); break; case 'm': /* Number of files */ n = ntags(); if (n) ap_int(n); else ap_int(nifile()); break; case 'p': /* Percent into file (bytes) */ pos = curr_byte(where); len = ch_length(); if (pos != -1 && len > 0) ap_int(percentage(pos, len)); else ap_quest(); break; case 'P': /* Percent into file (lines) */ linenum = currline(where); if (linenum == 0 || (len = ch_length()) == -1 || 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(); if (len != -1) ap_pos(len); else ap_quest(); break; case 't': /* Truncate trailing spaces in the message */ while (mp > message && mp[-1] == ' ') mp--; *mp = '\0'; break; case 'T': /* Type of list */ if (ntags()) ap_str("tag"); else ap_str("file"); break; case 'x': /* Name of next file */ h = next_ifile(curr_ifile); if (h != NULL) ap_str(get_filename(h)); else ap_quest(); break; } }