Annotation of embedaddon/bird2/client/birdc.c, revision 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>