home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / useful / text / show / less / source / source.lha / command.c < prev    next >
C/C++ Source or Header  |  1993-01-21  |  25KB  |  805 lines

  1. /*
  2.  * User-level command processor.
  3.  */
  4.  
  5. #include "less.h"
  6.  
  7. #include "position.h"
  8. #include <setjmp.h>
  9.  
  10. extern jmp_buf main_loop;
  11. extern int erase_char, kill_char;
  12. extern int pr_type;
  13. extern int sigs;
  14. extern int ispipe;
  15. extern int quit_at_eof;
  16. extern int hit_eof;
  17. extern int sc_width, sc_height;
  18. extern int sc_window;
  19. extern char *first_cmd;
  20. extern char *every_first_cmd;
  21. extern char version[];
  22. extern char current_file[];
  23. extern char *editor;
  24.  
  25. #ifdef AMIGA
  26. extern int scroll;
  27. extern curr_ac, ac;             /* local argc for file names */
  28. extern char **av;
  29. int user_errors = 0;
  30. #endif
  31.  
  32. static char cmdbuf[90];         /* Buffer for holding a multi-char command */
  33. #if SHELL_ESCAPE
  34. static char shellcmd[200];      /* For holding last shell command for "!!" */
  35. #endif
  36. static char *cp;                /* Pointer into cmdbuf */
  37. static int cmd_col;             /* Current column of the multi-char command */
  38. static char mcc;                /* The multi-char command letter (e.g. '/') */
  39. static char last_mcc;           /* The previous mcc */
  40. #ifdef AMIGA
  41. int screen_trashed;             /* The screen has been overwritten */
  42. #else
  43. static int screen_trashed;      /* The screen has been overwritten */
  44. #endif
  45.  
  46. /* Prototypes for functions defined in command.c */
  47.  
  48. static int cmd_erase __PROTO((void));
  49. static int cmd_char __PROTO((int c));
  50. static int cmd_int __PROTO((void));
  51. static void cmd_exec __PROTO((void));
  52. static void prompt __PROTO((void));
  53. static int getcc __PROTO((void));
  54.  
  55.  
  56. /*
  57.  * Reset command buffer (to empty).
  58.  */
  59. #ifdef __STDC__
  60. void cmd_reset (void)
  61. #else
  62. cmd_reset()
  63. #endif
  64. {
  65.         cp = cmdbuf;
  66. }
  67.  
  68. /*
  69.  * Backspace in command buffer.
  70.  */
  71. #ifdef __STDC__
  72. static int cmd_erase (void)
  73. #else
  74.         static int
  75. cmd_erase()
  76. #endif
  77. {
  78.         if (cp == cmdbuf)
  79.                 /*
  80.                  * Backspace past beginning of the string:
  81.                  * this usually means abort the command.
  82.                  */
  83.                 return (1);
  84.  
  85.         if (control_char(*--cp))
  86.         {
  87.                 /*
  88.                  * Erase an extra character, for the carat.
  89.                  */
  90.                 backspace();
  91.                 cmd_col--;
  92.         }
  93.         backspace();
  94.         cmd_col--;
  95.         return (0);
  96. }
  97.  
  98. /*
  99.  * Set up the display to start a new multi-character command.
  100.  */
  101. #ifdef __STDC__
  102. void start_mcc (int c)
  103. #else
  104. start_mcc(c)
  105.         int c;
  106. #endif
  107. {
  108.         mcc = c;
  109.         lower_left();
  110.         clear_eol();
  111.         putchr(mcc);
  112.         cmd_col = 1;
  113. }
  114.  
  115. /*
  116.  * Process a single character of a multi-character command, such as
  117.  * a number, or the pattern of a search command.
  118.  */
  119. #ifdef __STDC__
  120. static int cmd_char (int c)
  121. #else
  122.         static int
  123. cmd_char(c)
  124.         int c;
  125. #endif
  126. {
  127.         if (c == erase_char)
  128.         {
  129.                 if (cmd_erase())
  130.                         return (1);
  131.         } else if (c == kill_char)
  132.         {
  133.                 /* {{ Could do this faster, but who cares? }} */
  134.                 while (cmd_erase() == 0)
  135.                         ;
  136.         } else
  137.         {
  138.                 /*
  139.                  * Append the character to the string,
  140.                  * if there is room in the buffer and on the screen.
  141.                  */
  142.                 if (cp < &cmdbuf[sizeof(cmdbuf)-1] && cmd_col < sc_width-3)
  143.                 {
  144.                         *cp++ = c;
  145.                         if (control_char(c))
  146.                         {
  147.                                 putchr('^');
  148.                                 cmd_col++;
  149.                                 c = carat_char(c);
  150.                         }
  151.                         putchr(c);
  152.                         cmd_col++;
  153.                 } else
  154.                         bell();
  155.         }
  156.         return (0);
  157. }
  158.  
  159. /*
  160.  * Return the number currently in the command buffer.
  161.  */
  162. #ifdef __STDC__
  163. static int cmd_int (void)
  164. #else
  165.         static int
  166. cmd_int()
  167. #endif
  168. {
  169.         *cp = '\0';
  170.         cp = cmdbuf;
  171.         return (atoi(cmdbuf));
  172. }
  173.  
  174. /*
  175.  * Move the cursor to lower left before executing a command.
  176.  * This looks nicer if the command takes a long time before
  177.  * updating the screen.
  178.  */
  179. #ifdef __STDC__
  180. static void cmd_exec (void)
  181. #else
  182.         static void
  183. cmd_exec()
  184. #endif
  185. {
  186.         lower_left();
  187.         flush();
  188. }
  189.  
  190. /*
  191.  * Display the appropriate prompt.
  192.  */
  193. #ifdef __STDC__
  194. static void prompt (void)
  195. #else
  196.         static void
  197. prompt()
  198. #endif
  199. {
  200.         register char *p;
  201.  
  202.         if (first_cmd != NULL && *first_cmd != '\0')
  203.                 /*
  204.                  * No prompt necessary if commands are from first_cmd
  205.                  * rather than from the user.
  206.                  */
  207.                 return;
  208.  
  209.         /*
  210.          * If nothing is displayed yet, display starting from line 1.
  211.          */
  212.         if (position(TOP) == NULL_POSITION)
  213.                 jump_back(1);
  214.         else if (screen_trashed)
  215.                 repaint();
  216.         screen_trashed = 0;
  217.  
  218.         /*
  219.          * Select the proper prompt and display it.
  220.          */
  221.         lower_left();
  222.         clear_eol();
  223.         p = pr_string();
  224.         if (p == NULL)
  225.                 putchr(':');
  226.         else
  227.         {
  228. #ifdef AMIGA
  229.                 if ( strlen(p) > sc_width )
  230.                     screen_trashed = 1;
  231. #endif
  232.                 so_enter();
  233.                 putstr(p);
  234.                 so_exit();
  235.         }
  236. }
  237.  
  238. /*
  239.  * Get command character.
  240.  * The character normally comes from the keyboard,
  241.  * but may come from the "first_cmd" string.
  242.  */
  243. #ifdef __STDC__
  244. static int getcc (void)
  245. #else
  246.         static int
  247. getcc()
  248. #endif
  249. {
  250.         if (first_cmd == NULL)
  251.                 return (getchr());
  252.  
  253.         if (*first_cmd == '\0')
  254.         {
  255.                 /*
  256.                  * Reached end of first_cmd input.
  257.                  */
  258.                 first_cmd = NULL;
  259.                 if (cp > cmdbuf && position(TOP) == NULL_POSITION)
  260.                 {
  261.                         /*
  262.                          * Command is incomplete, so try to complete it.
  263.                          * There are only two cases:
  264.                          * 1. We have "/string" but no newline.  Add the \n.
  265.                          * 2. We have a number but no command.  Treat as #g.
  266.                          * (This is all pretty hokey.)
  267.                          */
  268.                         if (mcc != ':')
  269.                                 /* Not a number; must be search string */
  270.                                 return ('\n');
  271.                         else
  272.                                 /* A number; append a 'g' */
  273.                                 return ('g');
  274.                 }
  275.                 return (getchr());
  276.         }
  277.         return (int)(*first_cmd++);
  278. }
  279.  
  280. /*
  281.  * Main command processor.
  282.  * Accept and execute commands until a quit command, then return.
  283.  */
  284. #ifdef __STDC__
  285. void commands (void)
  286. #else
  287.         public void
  288. commands()
  289. #endif
  290. {
  291.         register int c;
  292.         register int n;
  293. #ifndef AMIGA
  294.         register int scroll = 10;
  295. #endif
  296.  
  297.         last_mcc = 0;
  298.         n = 0;
  299.         setjmp(main_loop);
  300.         mcc = 0;
  301.  
  302.         for (;;)
  303.         {
  304.                 /*
  305.                  * Display prompt and accept a character.
  306.                  */
  307.                 psignals();     /* See if any signals need processing */
  308.  
  309. #ifdef AMIGA
  310.                 if (quit_at_eof == 2 && hit_eof > 1)
  311. #else
  312.                 if (quit_at_eof && (quit_at_eof + hit_eof) > 2)
  313. #endif
  314.                         /*
  315.                          * After hitting end-of-file for the second time,
  316.                          * automatically advance to the next file.
  317.                          * If there are no more files, quit.
  318.                          */
  319.                         next_file(1);
  320.                 cmd_reset();
  321.                 prompt();
  322.                 c = getcc();
  323.  
  324.         again:
  325.                 if (sigs)
  326.                         continue;
  327.                 if (mcc)
  328.                 {
  329.                         /*
  330.                          * We are in a multi-character command.
  331.                          * All chars until newline go into the command buffer.
  332.                          * (Note that mcc == ':' is a special case that
  333.                          *  means a number is being entered.)
  334.                          */
  335.                         if (mcc != ':' && (c == '\n' || c == '\r