[BACK]Return to prompt.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Diff for /src/usr.bin/less/prompt.c between version 1.13 and 1.14

version 1.13, 2014/04/25 13:38:21 version 1.14, 2015/11/05 22:08:44
Line 6 
Line 6 
  *   *
  * For more information, see the README file.   * For more information, see the README file.
  */   */
   /*
    * Modified for use with illumos.
    * Copyright 2014 Garrett D'Amore <garrett@damore.org>
    */
   
   
 /*  /*
  * Prompting and other messages.   * Prompting and other messages.
  * There are three flavors of prompts, SHORT, MEDIUM and LONG,   * There are three flavors of prompts, SHORT, MEDIUM and LONG,
  * selected by the -m/-M options.   * selected by the -m/-M options.
  * There is also the "equals message", printed by the = command.   * There is also the "equals message", printed by the = command.
  * A prompt is a message composed of various pieces, such as the   * A prompt is a message composed of various pieces, such as the
  * name of the file being viewed, the percentage into the file, etc.   * name of the file being viewed, the percentage into the file, etc.
  */   */
   
Line 30 
Line 33 
 extern int jump_sline;  extern int jump_sline;
 extern int less_is_more;  extern int less_is_more;
 extern IFILE curr_ifile;  extern IFILE curr_ifile;
 #if EDITOR  
 extern char *editor;  extern char *editor;
 extern char *editproto;  extern char *editproto;
 #endif  
   
 /*  /*
  * Prototypes for the three flavors of prompts.   * Prototypes for the three flavors of prompts.
  * These strings are expanded by pr_expand().   * These strings are expanded by pr_expand().
  */   */
 static constant char s_proto[] =  static const char s_proto[] =
   "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x..%t";          "?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x..%t";
 static constant char m_proto[] =  static const char m_proto[] =
   "?f%f .?m(%T %i of %m) .?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t";          "?n?f%f .?m(%T %i of %m) ..?e(END) "
 static constant char M_proto[] =          "?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t";
   "?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 const char M_proto[] =
 static constant char e_proto[] =          "?f%f .?n?m(%T %i of %m) ..?"
   "?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t";          "ltlines %lt-%lb?L/%L. :byte %bB?s/%s. .?e(END)"
 static constant char h_proto[] =          " ?x- Next\\: %x.:?pB%pB\\%..%t";
   "HELP -- ?eEND -- Press g to see it again:Press RETURN for more., or q when done";  static const char e_proto[] =
 static constant char w_proto[] =          "?f%f .?m(%T %i of %m) .?ltlines "
   "Waiting for data";          "%lt-%lb?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t";
   static const char h_proto[] =
           "HELP -- ?eEND -- Press g to see it again:"
           "Press RETURN for more., or q when done";
   static const char w_proto[] =
           "Waiting for data";
   static const char more_proto[] =
           "%f (?eEND ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t)";
   static const char more_M_proto[] =
           "%f (?eEND ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t)"
           "[Press space to continue, q to quit, h for help]";
   
 public char *prproto[3];  char *prproto[3];
 public char constant *eqproto = e_proto;  char const *eqproto = e_proto;
 public char constant *hproto = h_proto;  char const *hproto = h_proto;
 public char constant *wproto = w_proto;  char const *wproto = w_proto;
   
 static char message[PROMPT_SIZE];  static char message[PROMPT_SIZE];
 static char *mp;  static char *mp;
Line 63 
Line 74 
 /*  /*
  * Initialize the prompt prototype strings.   * Initialize the prompt prototype strings.
  */   */
         public void  void
 init_prompt()  init_prompt(void)
 {  {
         prproto[0] = save(s_proto);          prproto[0] = save(s_proto);
         prproto[1] = save(m_proto);          prproto[1] = save(less_is_more ? more_proto : m_proto);
         prproto[2] = save(M_proto);          prproto[2] = save(less_is_more ? more_M_proto : M_proto);
         eqproto = save(e_proto);          eqproto = save(e_proto);
         hproto = save(h_proto);          hproto = save(h_proto);
         wproto = save(w_proto);          wproto = save(w_proto);
Line 77 
Line 88 
 /*  /*
  * Append a string to the end of the message.   * Append a string to the end of the message.
  */   */
         static void  static void
 ap_str(s)  ap_str(char *s)
         char *s;  
 {  {
         int len;          int len;
   
         len = strlen(s);          len = strlen(s);
         if (mp + len >= message + PROMPT_SIZE)          if (mp + len >= message + PROMPT_SIZE)
                 len = message + PROMPT_SIZE - mp - 1;                  len = message + PROMPT_SIZE - mp - 1;
         strncpy(mp, s, len);          (void) strncpy(mp, s, len);
         mp += len;          mp += len;
         *mp = '\0';          *mp = '\0';
 }  }
Line 94 
Line 104 
 /*  /*
  * Append a character to the end of the message.   * Append a character to the end of the message.
  */   */
         static void  static void
 ap_char(c)  ap_char(char c)
         char c;  
 {  {
         char buf[2];          char buf[2];
   
Line 106 
Line 115 
 }  }
   
 /*  /*
  * Append a POSITION (as a decimal integer) to the end of the message.   * Append a off_t (as a decimal integer) to the end of the message.
  */   */
         static void  static void
 ap_pos(pos)  ap_pos(off_t pos)
         POSITION pos;  
 {  {
         char buf[INT_STRLEN_BOUND(pos) + 2];          char buf[INT_STRLEN_BOUND(pos) + 2];
   
         postoa(pos, buf, sizeof(buf));          postoa(pos, buf, sizeof buf);
         ap_str(buf);          ap_str(buf);
 }  }
   
 /*  /*
  * Append a line number to the end of the message.   * Append a line number to the end of the message.
  */   */
         static void  static void
 ap_linenum(linenum)  ap_linenum(LINENUM linenum)
         LINENUM linenum;  
 {  {
         char buf[INT_STRLEN_BOUND(linenum) + 2];          char buf[INT_STRLEN_BOUND(linenum) + 2];
   
         linenumtoa(linenum, buf, sizeof(buf));          linenumtoa(linenum, buf, sizeof buf);
         ap_str(buf);          ap_str(buf);
 }  }
   
 /*  /*
  * Append an integer to the end of the message.   * Append an integer to the end of the message.
  */   */
         static void  static void
 ap_int(num)  ap_int(int num)
         int num;  
 {  {
         char buf[INT_STRLEN_BOUND(num) + 2];          char buf[INT_STRLEN_BOUND(num) + 2];
   
         inttoa(num, buf, sizeof(buf));          inttoa(num, buf, sizeof buf);
         ap_str(buf);          ap_str(buf);
 }  }
   
 /*  /*
  * Append a question mark to the end of the message.   * Append a question mark to the end of the message.
  */   */
         static void  static void
 ap_quest()  ap_quest(void)
 {  {
         ap_str("?");          ap_str("?");
 }  }
Line 156 
Line 162 
 /*  /*
  * Return the "current" byte offset in the file.   * Return the "current" byte offset in the file.
  */   */
         static POSITION  static off_t
 curr_byte(where)  curr_byte(int where)
         int where;  
 {  {
         POSITION pos;          off_t pos;
   
         pos = position(where);          pos = position(where);
         while (pos == NULL_POSITION && where >= 0 && where < sc_height-1)          while (pos == -1 && where >= 0 && where < sc_height-1)
                 pos = position(++where);                  pos = position(++where);
         if (pos == NULL_POSITION)          if (pos == -1)
                 pos = ch_length();                  pos = ch_length();
         return (pos);          return (pos);
 }  }
   
 /*  /*
  * Return the value of a prototype conditional.   * Return the value of a prototype conditional.
  * A prototype string may include conditionals which consist of a   * A prototype string may include conditionals which consist of a
  * question mark followed by a single letter.   * question mark followed by a single letter.
  * Here we decode that letter and return the appropriate boolean value.   * Here we decode that letter and return the appropriate boolean value.
  */   */
         static int  static int
 cond(c, where)  cond(char c, int where)
         char c;  
         int where;  
 {  {
         POSITION len;          off_t len;
   
         switch (c)          switch (c) {
         {  
         case 'a':       /* Anything in the message yet? */          case 'a':       /* Anything in the message yet? */
                 return (mp > message);                  return (mp > message);
         case 'b':       /* Current byte offset known? */          case 'b':       /* Current byte offset known? */
                 return (curr_byte(where) != NULL_POSITION);                  return (curr_byte(where) != -1);
         case 'c':          case 'c':
                 return (hshift != 0);                  return (hshift != 0);
         case 'e':       /* At end of file? */          case 'e':       /* At end of file? */
Line 200 
Line 202 
                 return (linenums);                  return (linenums);
         case 'L':       /* Final line number known? */          case 'L':       /* Final line number known? */
         case 'D':       /* Final page number known? */          case 'D':       /* Final page number known? */
                 return (linenums && ch_length() != NULL_POSITION);                  return (linenums && ch_length() != -1);
         case 'm':       /* More than one file? */          case 'm':       /* More than one file? */
 #if TAGS  
                 return (ntags() ? (ntags() > 1) : (nifile() > 1));                  return (ntags() ? (ntags() > 1) : (nifile() > 1));
 #else  
                 return (nifile() > 1);  
 #endif  
         case 'n':       /* First prompt in a new file? */          case 'n':       /* First prompt in a new file? */
 #if TAGS  
                 return (ntags() ? 1 : new_file);                  return (ntags() ? 1 : new_file);
 #else  
                 return (new_file);  
 #endif  
         case 'p':       /* Percent into file (bytes) known? */          case 'p':       /* Percent into file (bytes) known? */
                 return (curr_byte(where) != NULL_POSITION &&                  return (curr_byte(where) != -1 && ch_length() > 0);
                                 ch_length() > 0);  
         case 'P':       /* Percent into file (lines) known? */          case 'P':       /* Percent into file (lines) known? */
                 return (currline(where) != 0 &&                  return (currline(where) != 0 &&
                                 (len = ch_length()) > 0 &&                      (len = ch_length()) > 0 && find_linenum(len) != 0);
                                 find_linenum(len) != 0);  
         case 's':       /* Size of file known? */          case 's':       /* Size of file known? */
         case 'B':          case 'B':
                 return (ch_length() != NULL_POSITION);                  return (ch_length() != -1);
         case 'x':       /* Is there a "next" file? */          case 'x':       /* Is there a "next" file? */
 #if TAGS  
                 if (ntags())                  if (ntags())
                         return (0);                          return (0);
 #endif  
                 return (next_ifile(curr_ifile) != NULL_IFILE);                  return (next_ifile(curr_ifile) != NULL_IFILE);
         }          }
         return (0);          return (0);
Line 240 
Line 230 
  * Here we decode that letter and take the appropriate action,   * Here we decode that letter and take the appropriate action,
  * usually by appending something to the message being built.   * usually by appending something to the message being built.
  */   */
         static void  static void
 protochar(c, where, iseditproto)  protochar(int c, int where)
         int c;  
         int where;  
         int iseditproto;  
 {  {
         POSITION pos;          off_t pos;
         POSITION len;          off_t len;
         int n;          int n;
         LINENUM linenum;          LINENUM linenum;
         LINENUM last_linenum;          LINENUM last_linenum;
         IFILE h;          IFILE h;
   
 #undef  PAGE_NUM  #undef  PAGE_NUM
 #define PAGE_NUM(linenum)  ((((linenum) - 1) / (sc_height - 1)) + 1)  #define PAGE_NUM(linenum)  ((((linenum) - 1) / (sc_height - 1)) + 1)
   
         switch (c)          switch (c) {
         {  
         case 'b':       /* Current byte offset */          case 'b':       /* Current byte offset */
                 pos = curr_byte(where);                  pos = curr_byte(where);
                 if (pos != NULL_POSITION)                  if (pos != -1)
                         ap_pos(pos);                          ap_pos(pos);
                 else                  else
                         ap_quest();                          ap_quest();
Line 278 
Line 264 
         case 'D':       /* Final page number */          case 'D':       /* Final page number */
                 /* Find the page number of the last byte in the file (len-1). */                  /* Find the page number of the last byte in the file (len-1). */
                 len = ch_length();                  len = ch_length();
                 if (len == NULL_POSITION)                  if (len == -1) {
                         ap_quest();                          ap_quest();
                 else if (len == 0)                  } else if (len == 0) {
                         /* An empty file has no pages. */                          /* An empty file has no pages. */
                         ap_linenum(0);                          ap_linenum(0);
                 else                  } else {
                 {  
                         linenum = find_linenum(len - 1);                          linenum = find_linenum(len - 1);
                         if (linenum <= 0)                          if (linenum <= 0)
                                 ap_quest();                                  ap_quest();
                         else                          else
                                 ap_linenum(PAGE_NUM(linenum));                                  ap_linenum(PAGE_NUM(linenum));
                 }                  }
                 break;                  break;
 #if EDITOR  
         case 'E':       /* Editor name */          case 'E':       /* Editor name */
                 ap_str(editor);                  ap_str(editor);
                 break;                  break;
 #endif  
         case 'f':       /* File name */          case 'f':       /* File name */
                 ap_str(get_filename(curr_ifile));                  ap_str(get_filename(curr_ifile));
                 break;                  break;
Line 304 
Line 287 
                 ap_str(last_component(get_filename(curr_ifile)));                  ap_str(last_component(get_filename(curr_ifile)));
                 break;                  break;
         case 'i':       /* Index into list of files */          case 'i':       /* Index into list of files */
 #if TAGS  
                 if (ntags())                  if (ntags())
                         ap_int(curr_tag());                          ap_int(curr_tag());
                 else                  else
 #endif  
                         ap_int(get_index(curr_ifile));                          ap_int(get_index(curr_ifile));
                 break;                  break;
         case 'l':       /* Current line number */          case 'l':       /* Current line number */
Line 320 
Line 301 
                 break;                  break;
         case 'L':       /* Final line number */          case 'L':       /* Final line number */
                 len = ch_length();                  len = ch_length();
                 if (len == NULL_POSITION || len == ch_zero() ||                  if (len == -1 || len == ch_zero() ||
                     (linenum = find_linenum(len)) <= 0)                      (linenum = find_linenum(len)) <= 0)
                         ap_quest();                          ap_quest();
                 else                  else
                         ap_linenum(linenum-1);                          ap_linenum(linenum-1);
                 break;                  break;
         case 'm':       /* Number of files */          case 'm':       /* Number of files */
 #if TAGS  
                 n = ntags();                  n = ntags();
                 if (n)                  if (n)
                         ap_int(n);                          ap_int(n);
                 else                  else
 #endif  
                         ap_int(nifile());                          ap_int(nifile());
                 break;                  break;
         case 'p':       /* Percent into file (bytes) */          case 'p':       /* Percent into file (bytes) */
                 pos = curr_byte(where);                  pos = curr_byte(where);
                 len = ch_length();                  len = ch_length();
                 if (pos != NULL_POSITION && len > 0)                  if (pos != -1 && len > 0)
                         ap_int(percentage(pos,len));                          ap_int(percentage(pos, len));
                 else                  else
                         ap_quest();                          ap_quest();
                 break;                  break;
         case 'P':       /* Percent into file (lines) */          case 'P':       /* Percent into file (lines) */
                 linenum = currline(where);                  linenum = currline(where);
                 if (linenum == 0 ||                  if (linenum == 0 ||
                     (len = ch_length()) == NULL_POSITION || len == ch_zero() ||                      (len = ch_length()) == -1 || len == ch_zero() ||
                     (last_linenum = find_linenum(len)) <= 0)                      (last_linenum = find_linenum(len)) <= 0)
                         ap_quest();                          ap_quest();
                 else                  else
Line 355 
Line 334 
         case 's':       /* Size of file */          case 's':       /* Size of file */
         case 'B':          case 'B':
                 len = ch_length();                  len = ch_length();
                 if (len != NULL_POSITION)                  if (len != -1)
                         ap_pos(len);                          ap_pos(len);
                 else                  else
                         ap_quest();                          ap_quest();
Line 366 
Line 345 
                 *mp = '\0';                  *mp = '\0';
                 break;                  break;
         case 'T':       /* Type of list */          case 'T':       /* Type of list */
 #if TAGS  
                 if (ntags())                  if (ntags())
                         ap_str("tag");                          ap_str("tag");
                 else                  else
 #endif  
                         ap_str("file");                          ap_str("file");
                 break;                  break;
         case 'x':       /* Name of next file */          case 'x':       /* Name of next file */
Line 385 
Line 362 
   
 /*  /*
  * Skip a false conditional.   * Skip a false conditional.
  * When a false condition is found (either a false IF or the ELSE part   * When a false condition is found (either a false IF or the ELSE part
  * of a true IF), this routine scans the prototype string to decide   * of a true IF), this routine scans the prototype string to decide
  * where to resume parsing the string.   * where to resume parsing the string.
  * We must keep track of nested IFs and skip them properly.   * We must keep track of nested IFs and skip them properly.
  */   */
         static constant char *  static const char *
 skipcond(p)  skipcond(const char *p)
         register constant char *p;  
 {  {
         register int iflevel;          int iflevel;
   
         /*          /*
          * We came in here after processing a ? or :,           * We came in here after processing a ? or :,
Line 402 
Line 378 
          */           */
         iflevel = 1;          iflevel = 1;
   
         for (;;) switch (*++p)          for (;;) {
         {                  switch (*++p) {
         case '?':                  case '?':
                 /*                          /*
                  * Start of a nested IF.                           * Start of a nested IF.
                  */                           */
                 iflevel++;                          iflevel++;
                 break;                          break;
         case ':':                  case ':':
                 /*                          /*
                  * Else.                           * Else.
                  * If this matches the IF we came in here with,                           * If this matches the IF we came in here with,
                  * then we're done.                           * then we're done.
                  */                           */
                 if (iflevel == 1)                          if (iflevel == 1)
                         return (p);                                  return (p);
                 break;                          break;
         case '.':                  case '.':
                 /*                          /*
                  * Endif.                           * Endif.
                  * If this matches the IF we came in here with,                           * If this matches the IF we came in here with,
                  * then we're done.                           * then we're done.
                  */                           */
                 if (--iflevel == 0)                          if (--iflevel == 0)
                         return (p);                                  return (p);
                 break;                          break;
         case '\\':                  case '\\':
                 /*                          /*
                  * Backslash escapes the next character.                           * Backslash escapes the next character.
                  */                           */
                 ++p;                          ++p;
                 break;                          break;
         case '\0':                  case '\0':
                 /*                          /*
                  * Whoops.  Hit end of string.                           * Whoops.  Hit end of string.
                  * This is a malformed conditional, but just treat it                           * This is a malformed conditional, but just treat it
                  * as if all active conditionals ends here.                           * as if all active conditionals ends here.
                  */                           */
                 return (p-1);                          return (p-1);
                   }
         }          }
         /*NOTREACHED*/          /*NOTREACHED*/
 }  }
Line 448 
Line 425 
 /*  /*
  * Decode a char that represents a position on the screen.   * Decode a char that represents a position on the screen.
  */   */
         static constant char *  static const char *
 wherechar(p, wp)  wherechar(const char *p, int *wp)
         char constant *p;  
         int *wp;  
 {  {
         switch (*p)          switch (*p) {
         {  
         case 'b': case 'd': case 'l': case 'p': case 'P':          case 'b': case 'd': case 'l': case 'p': case 'P':
                 switch (*++p)                  switch (*++p) {
                 {  
                 case 't':   *wp = TOP;                  break;                  case 't':   *wp = TOP;                  break;
                 case 'm':   *wp = MIDDLE;               break;                  case 'm':   *wp = MIDDLE;               break;
                 case 'b':   *wp = BOTTOM;               break;                  case 'b':   *wp = BOTTOM;               break;
Line 472 
Line 445 
 /*  /*
  * Construct a message based on a prototype string.   * Construct a message based on a prototype string.
  */   */
         public char *  char *
 pr_expand(proto, maxwidth)  pr_expand(const char *proto, int maxwidth)
         constant char *proto;  
         int maxwidth;  
 {  {
         register constant char *p;          const char *p;
         register int c;          int c;
         int where;          int where;
   
         mp = message;          mp = message;
Line 486 
Line 457 
         if (*proto == '\0')          if (*proto == '\0')
                 return ("");                  return ("");
   
         for (p = proto;  *p != '\0';  p++)          for (p = proto; *p != '\0'; p++) {
         {                  switch (*p) {
                 switch (*p)  
                 {  
                 default:        /* Just put the character in the message */                  default:        /* Just put the character in the message */
                         ap_char(*p);                          ap_char(*p);
                         break;                          break;
Line 498 
Line 467 
                         ap_char(*p);                          ap_char(*p);
                         break;                          break;
                 case '?':       /* Conditional (IF) */                  case '?':       /* Conditional (IF) */
                         if ((c = *++p) == '\0')                          if ((c = *++p) == '\0') {
                                 --p;                                  --p;
                         else                          } else {
                         {  
                                 where = 0;                                  where = 0;
                                 p = wherechar(p, &where);                                  p = wherechar(p, &where);
                                 if (!cond(c, where))                                  if (!cond(c, where))
Line 514 
Line 482 
                 case '.':       /* ENDIF */                  case '.':       /* ENDIF */
                         break;                          break;
                 case '%':       /* Percent escape */                  case '%':       /* Percent escape */
                         if ((c = *++p) == '\0')                          if ((c = *++p) == '\0') {
                                 --p;                                  --p;
                         else                          } else {
                         {  
                                 where = 0;                                  where = 0;
                                 p = wherechar(p, &where);                                  p = wherechar(p, &where);
                                 protochar(c, where,                                  protochar(c, where);
 #if EDITOR  
                                         (proto == editproto));  
 #else  
                                         0);  
 #endif  
   
                         }                          }
                         break;                          break;
                 }                  }
Line 534 
Line 495 
   
         if (mp == message)          if (mp == message)
                 return ("");                  return ("");
         if (maxwidth > 0 && mp >= message + maxwidth)          if (maxwidth > 0 && mp >= message + maxwidth) {
         {  
                 /*                  /*
                  * Message is too long.                   * Message is too long.
                  * Return just the final portion of it.                   * Return just the final portion of it.
Line 548 
Line 508 
 /*  /*
  * Return a message suitable for printing by the "=" command.   * Return a message suitable for printing by the "=" command.
  */   */
         public char *  char *
 eq_message()  eq_message(void)
 {  {
         return (pr_expand(eqproto, 0));          return (pr_expand(eqproto, 0));
 }  }
Line 560 
Line 520 
  * If we can't come up with an appropriate prompt, return NULL   * If we can't come up with an appropriate prompt, return NULL
  * and the caller will prompt with a colon.   * and the caller will prompt with a colon.
  */   */
         public char *  char *
 pr_string()  prompt_string(void)
 {  {
         char *prompt;          char *prompt;
         int type;          int type;
   
         type = (!less_is_more) ? pr_type : pr_type ? 0 : 1;          type = pr_type;
         prompt = pr_expand((ch_getflags() & CH_HELPFILE) ?          prompt = pr_expand((ch_getflags() & CH_HELPFILE) ?
                                 hproto : prproto[type],              hproto : prproto[type], sc_width-so_s_width-so_e_width-2);
                         sc_width-so_s_width-so_e_width-2);  
         new_file = 0;          new_file = 0;
         return (prompt);          return (prompt);
 }  }
Line 577 
Line 536 
 /*  /*
  * Return a message suitable for printing while waiting in the F command.   * Return a message suitable for printing while waiting in the F command.
  */   */
         public char *  char *
 wait_message()  wait_message(void)
 {  {
         return (pr_expand(wproto, sc_width-so_s_width-so_e_width-2));          return (pr_expand(wproto, sc_width-so_s_width-so_e_width-2));
 }  }

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14