File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / client / birdc.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /*
    2:  *	BIRD Client - Readline variant I/O
    3:  *
    4:  *	(c) 1999--2004 Martin Mares <mj@ucw.cz>
    5:  *
    6:  *	Can be freely distributed and used under the terms of the GNU GPL.
    7:  */
    8: 
    9: #include <stdio.h>
   10: #include <stdlib.h>
   11: #include <unistd.h>
   12: #include <termios.h>
   13: 
   14: #include <readline/readline.h>
   15: #include <readline/history.h>
   16: #include <curses.h>
   17: 
   18: #include "nest/bird.h"
   19: #include "lib/resource.h"
   20: #include "lib/string.h"
   21: #include "client/client.h"
   22: 
   23: static int input_hidden_end;
   24: static int prompt_active;
   25: 
   26: /*** Input ***/
   27: 
   28: /* HACK: libreadline internals we need to access */
   29: extern int _rl_vis_botlin;
   30: extern void _rl_move_vert(int);
   31: 
   32: static void
   33: add_history_dedup(char *cmd)
   34: {
   35:   /* Add history line if it differs from the last one */
   36:   HIST_ENTRY *he = history_get(history_length);
   37:   if (!he || strcmp(he->line, cmd))
   38:     add_history(cmd);
   39: }
   40: 
   41: static void
   42: input_got_line(char *cmd_buffer)
   43: {
   44:   if (!cmd_buffer)
   45:     {
   46:       cleanup();
   47:       exit(0);
   48:     }
   49: 
   50:   if (cmd_buffer[0])
   51:     {
   52:       add_history_dedup(cmd_buffer);
   53:       submit_command(cmd_buffer);
   54:     }
   55: 
   56:   free(cmd_buffer);
   57: }
   58: 
   59: void
   60: input_start_list(void)
   61: {
   62:   /* Leave the currently edited line and make space for listing */
   63:   _rl_move_vert(_rl_vis_botlin);
   64: #ifdef HAVE_RL_CRLF
   65:   rl_crlf();
   66: #endif
   67: }
   68: 
   69: void
   70: input_stop_list(void)
   71: {
   72:   /* Reprint the currently edited line after listing */
   73:   rl_on_new_line();
   74:   rl_redisplay();
   75: }
   76: 
   77: static int
   78: input_complete(int arg UNUSED, int key UNUSED)
   79: {
   80:   static int complete_flag;
   81:   char buf[256];
   82: 
   83:   if (rl_last_func != input_complete)
   84:     complete_flag = 0;
   85:   switch (cmd_complete(rl_line_buffer, rl_point, buf, complete_flag))
   86:     {
   87:     case 0:
   88:       complete_flag = 1;
   89:       break;
   90:     case 1:
   91:       rl_insert_text(buf);
   92:       break;
   93:     default:
   94:       complete_flag = 1;
   95: #ifdef HAVE_RL_DING
   96:       rl_ding();
   97: #endif
   98:     }
   99:   return 0;
  100: }
  101: 
  102: static int
  103: input_help(int arg, int key UNUSED)
  104: {
  105:   int i, in_string, in_bracket;
  106: 
  107:   if (arg != 1)
  108:     return rl_insert(arg, '?');
  109: 
  110:   in_string = in_bracket = 0;
  111:   for (i = 0; i < rl_point; i++)
  112:     {
  113:    
  114:       if (rl_line_buffer[i] == '"')
  115: 	in_string = ! in_string;
  116:       else if (! in_string)
  117:         {
  118: 	  if (rl_line_buffer[i] == '[')
  119: 	    in_bracket++;
  120: 	  else if (rl_line_buffer[i] == ']')
  121: 	    in_bracket--;
  122:         }
  123:     }
  124: 
  125:   /* `?' inside string or path -> insert */
  126:   if (in_string || in_bracket)
  127:     return rl_insert(1, '?');
  128: 
  129:   rl_begin_undo_group();		/* HACK: We want to display `?' at point position */
  130:   rl_insert_text("?");
  131:   rl_redisplay();
  132:   rl_end_undo_group();
  133:   input_start_list();
  134:   cmd_help(rl_line_buffer, rl_point);
  135:   rl_undo_command(1, 0);
  136:   input_stop_list();
  137:   return 0;
  138: }
  139: 
  140: void
  141: input_init(void)
  142: {
  143:   rl_readline_name = "birdc";
  144:   rl_add_defun("bird-complete", input_complete, '\t');
  145:   rl_add_defun("bird-help", input_help, '?');
  146:   rl_callback_handler_install("bird> ", input_got_line);
  147: 
  148:   // rl_get_screen_size();
  149:   term_lns = LINES;
  150:   term_cls = COLS;
  151: 
  152:   prompt_active = 1;
  153: 
  154:   // readline library does strange things when stdin is nonblocking.
  155:   // if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
  156:   //   DIE("fcntl");
  157: }
  158: 
  159: static void
  160: input_reveal(void)
  161: {
  162:   /* need this, otherwise some lib seems to eat pending output when
  163:      the prompt is displayed */
  164:   fflush(stdout);
  165:   tcdrain(STDOUT_FILENO);
  166: 
  167:   rl_end = input_hidden_end;
  168:   rl_expand_prompt("bird> ");
  169:   rl_forced_update_display();
  170: 
  171:   prompt_active = 1;
  172: }
  173: 
  174: static void
  175: input_hide(void)
  176: {
  177:   input_hidden_end = rl_end;
  178:   rl_end = 0;
  179:   rl_expand_prompt("");
  180:   rl_redisplay();
  181: 
  182:   prompt_active = 0;
  183: }
  184: 
  185: void
  186: input_notify(int prompt)
  187: {
  188:   if (prompt == prompt_active)
  189:     return;
  190: 
  191:   if (prompt)
  192:     input_reveal();
  193:   else
  194:     input_hide();
  195: }
  196: 
  197: void
  198: input_read(void)
  199: {
  200:   rl_callback_read_char();
  201: }
  202: 
  203: void
  204: more_begin(void)
  205: {
  206: }
  207: 
  208: void
  209: more_end(void)
  210: {
  211: }
  212: 
  213: void
  214: cleanup(void)
  215: {
  216:   if (init)
  217:     return;
  218: 
  219:   input_hide();
  220:   rl_callback_handler_remove();
  221: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>