Statistics
| Branch: | Revision:

iof-bird / bird-2.0.1 / client / birdc.c @ 6b3f1a54

History | View | Annotate | Download (4.2 KB)

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
}