Annotation of embedaddon/bird2/client/birdc.c, revision 1.1.1.1

1.1       misho       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: #define HISTORY "/.birdc_history"
                     33: static char *history_file;
                     34: 
                     35: static void
                     36: add_history_dedup(char *cmd)
                     37: {
                     38:   /* Add history line if it differs from the last one */
                     39:   HIST_ENTRY *he = history_get(history_length);
                     40:   if (!he || strcmp(he->line, cmd))
                     41:     add_history(cmd);
                     42: }
                     43: 
                     44: static void
                     45: input_got_line(char *cmd_buffer)
                     46: {
                     47:   if (!cmd_buffer)
                     48:     {
                     49:       cleanup();
                     50:       exit(0);
                     51:     }
                     52: 
                     53:   if (cmd_buffer[0])
                     54:     {
                     55:       add_history_dedup(cmd_buffer);
                     56:       submit_command(cmd_buffer);
                     57:     }
                     58: 
                     59:   free(cmd_buffer);
                     60: }
                     61: 
                     62: void
                     63: input_start_list(void)
                     64: {
                     65:   /* Leave the currently edited line and make space for listing */
                     66:   _rl_move_vert(_rl_vis_botlin);
                     67: #ifdef HAVE_RL_CRLF
                     68:   rl_crlf();
                     69: #endif
                     70: }
                     71: 
                     72: void
                     73: input_stop_list(void)
                     74: {
                     75:   /* Reprint the currently edited line after listing */
                     76:   rl_on_new_line();
                     77:   rl_redisplay();
                     78: }
                     79: 
                     80: static int
                     81: input_complete(int arg UNUSED, int key UNUSED)
                     82: {
                     83:   static int complete_flag;
                     84:   char buf[256];
                     85: 
                     86:   if (rl_last_func != input_complete)
                     87:     complete_flag = 0;
                     88:   switch (cmd_complete(rl_line_buffer, rl_point, buf, complete_flag))
                     89:     {
                     90:     case 0:
                     91:       complete_flag = 1;
                     92:       break;
                     93:     case 1:
                     94:       rl_insert_text(buf);
                     95:       break;
                     96:     default:
                     97:       complete_flag = 1;
                     98: #ifdef HAVE_RL_DING
                     99:       rl_ding();
                    100: #endif
                    101:     }
                    102:   return 0;
                    103: }
                    104: 
                    105: static int
                    106: input_help(int arg, int key UNUSED)
                    107: {
                    108:   int i, in_string, in_bracket;
                    109: 
                    110:   if (arg != 1)
                    111:     return rl_insert(arg, '?');
                    112: 
                    113:   in_string = in_bracket = 0;
                    114:   for (i = 0; i < rl_point; i++)
                    115:     {
                    116:    
                    117:       if (rl_line_buffer[i] == '"')
                    118:        in_string = ! in_string;
                    119:       else if (! in_string)
                    120:         {
                    121:          if (rl_line_buffer[i] == '[')
                    122:            in_bracket++;
                    123:          else if (rl_line_buffer[i] == ']')
                    124:            in_bracket--;
                    125:         }
                    126:     }
                    127: 
                    128:   /* `?' inside string or path -> insert */
                    129:   if (in_string || in_bracket)
                    130:     return rl_insert(1, '?');
                    131: 
                    132:   rl_begin_undo_group();               /* HACK: We want to display `?' at point position */
                    133:   rl_insert_text("?");
                    134:   rl_redisplay();
                    135:   rl_end_undo_group();
                    136:   input_start_list();
                    137:   cmd_help(rl_line_buffer, rl_point);
                    138:   rl_undo_command(1, 0);
                    139:   input_stop_list();
                    140:   return 0;
                    141: }
                    142: 
                    143: void
                    144: history_init(void)
                    145: {
                    146:   const char *homedir = getenv("HOME");
                    147:   if (!homedir)
                    148:     homedir = ".";
                    149:   history_file = malloc(strlen(homedir) + sizeof(HISTORY));
                    150:   if (!history_file)
                    151:     die("couldn't alloc enough memory for history file name");
                    152: 
                    153:   sprintf(history_file, "%s%s", homedir, HISTORY);
                    154:   read_history(history_file);
                    155: }
                    156: 
                    157: void
                    158: input_init(void)
                    159: {
                    160:   if (interactive)
                    161:     history_init();
                    162:   rl_readline_name = "birdc";
                    163:   rl_add_defun("bird-complete", input_complete, '\t');
                    164:   rl_add_defun("bird-help", input_help, '?');
                    165:   rl_callback_handler_install("bird> ", input_got_line);
                    166: 
                    167:   // rl_get_screen_size();
                    168:   term_lns = LINES;
                    169:   term_cls = COLS;
                    170: 
                    171:   prompt_active = 1;
                    172: 
                    173:   // readline library does strange things when stdin is nonblocking.
                    174:   // if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
                    175:   //   DIE("fcntl");
                    176: }
                    177: 
                    178: static void
                    179: input_reveal(void)
                    180: {
                    181:   /* need this, otherwise some lib seems to eat pending output when
                    182:      the prompt is displayed */
                    183:   fflush(stdout);
                    184:   tcdrain(STDOUT_FILENO);
                    185: 
                    186:   rl_end = input_hidden_end;
                    187:   rl_expand_prompt("bird> ");
                    188:   rl_forced_update_display();
                    189: 
                    190:   prompt_active = 1;
                    191: }
                    192: 
                    193: static void
                    194: input_hide(void)
                    195: {
                    196:   input_hidden_end = rl_end;
                    197:   rl_end = 0;
                    198:   rl_expand_prompt("");
                    199:   rl_redisplay();
                    200: 
                    201:   prompt_active = 0;
                    202: }
                    203: 
                    204: void
                    205: input_notify(int prompt)
                    206: {
                    207:   if (prompt == prompt_active)
                    208:     return;
                    209: 
                    210:   if (prompt)
                    211:     input_reveal();
                    212:   else
                    213:     input_hide();
                    214: }
                    215: 
                    216: void
                    217: input_read(void)
                    218: {
                    219:   rl_callback_read_char();
                    220: }
                    221: 
                    222: void
                    223: more_begin(void)
                    224: {
                    225: }
                    226: 
                    227: void
                    228: more_end(void)
                    229: {
                    230: }
                    231: 
                    232: void
                    233: cleanup(void)
                    234: {
                    235:   if (init)
                    236:     return;
                    237: 
                    238:   input_hide();
                    239:   if (interactive)
                    240:     write_history(history_file);
                    241:   rl_callback_handler_remove();
                    242: }

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