FACT++  1.0
Shell.cc
Go to the documentation of this file.
1 // **************************************************************************
64 // **************************************************************************
65 #include "Shell.h"
66 
67 #include <fstream>
68 #include <iostream>
69 
70 #include <signal.h> // SIGWINCH
71 #include <sys/wait.h> // waitpid
72 #include <sys/ioctl.h> // ioctl
73 
74 #include <panel.h>
75 
76 #define FORK_ALLOWED
77 
78 using namespace std;
79 
80 Shell *Shell::This = 0;
81 
82 // --------------------------------------------------------------------------
83 //
94 //
95 Shell::Shell(const char *prgname) : ReadlineWindow(prgname),
96  fPanelHeight(13), fIsVisible(1), fLine(0)
97 {
98  if (stdscr!=0)
99  {
100  endwin();
101  cout << "ERROR - Only one instance of class Shell is allowed." << endl;
102  exit(-1);
103  }
104 
105  This = this;
106 
107  // ---------------------- Setup ncurses -------------------------
108 
109  initscr(); // Start curses mode
110 
111  cbreak(); // Line buffering disabled, Pass on
112  noecho(); // Switch off echo mode
113  nonl(); // Associate return with CR
114 
115  intrflush(stdscr, FALSE);
116  keypad(stdscr, FALSE); // Switch off keymapping for function keys
117 
118  start_color(); // Initialize ncurses colors
119  use_default_colors(); // Assign terminal default colors to -1
120  //assume_default_colors(-1, -1); // standard terminal colors assigned to pair 0
121 
122  // Setup colors
123  for (int i=1; i<8; i++)
124  init_pair(i, i, -1); // -1: def background
125 
126  signal(SIGWINCH, HandleResizeImp); // Attach HandleResize to SIGWINCH signal
127 
128  // ---------------------- Setup pansl --------------------------
129 
130  // Create the necessary windows
131  WINDOW *wins[4];
132  CreateWindows(wins);
133 
134  // Initialize the panels
135  fPanelIn = new_panel(wins[0]);
136  fPanelFrame = new_panel(wins[1]);
137  fPanelOut = new_panel(wins[2]);
138 
139  win.SetWindow(wins[0]);
140  wout.SetWindow(wins[2]);
141 
142  // Get the panels into the right order for startup
143  ShowHide(1);
144 
145  // Setup Readline
146  SetWindow(wins[0]);
147  SetColorPrompt(COLOR_PAIR(COLOR_BLUE));
148 
149  // ------------------- Setup key bindings -----------------------
150  BindKeySequence("\033OP", rl_proc_F1);
151  BindKeySequence("\033[1;5B", rl_scroll_top);
152  BindKeySequence("\033[1;5A", rl_scroll_top);
153  BindKeySequence("\033[1;3A", rl_scroll_bot);
154  BindKeySequence("\033[1;3B", rl_scroll_bot);
155  BindKeySequence("\033[5;3~", rl_top_inc);
156  BindKeySequence("\033[6;3~", rl_top_dec);
157  BindKeySequence("\033+", rl_top_resize);
158  BindKeySequence("\033-", rl_top_resize);
159 
160  /*
161  rl_bind_keyseq("\033\t", rl_complete); // Meta-Tab
162  rl_bind_keyseq("\033[1~", home); // Home (console)
163  rl_bind_keyseq("\033[H", home); // Home (x)
164  rl_bind_keyseq("\033[4~", end); // End (console)
165  rl_bind_keyseq("\033[F", end); // End (x)
166  rl_bind_keyseq("\033[A", up); // Up
167  rl_bind_keyseq("\033[B", down); // Down
168  rl_bind_keyseq("\033[[B", accept); // F2 (console)
169  rl_bind_keyseq("\033OQ", accept); // F2 (x)
170  rl_bind_keyseq("\033[21~", cancel); // F10
171  */
172 
173  // Ctrl+dn: \033[1;5B
174  // Ctrl+up: \033[1;5A
175  // Alt+up: \033[1;3A
176  // Alt+dn: \033[1;3B
177  // Alt+pg up: \033[5;3~
178  // Alt+pg dn: \033[6;3~
179 }
180 
181 // --------------------------------------------------------------------------
182 //
184 //
186 {
187  // Maybe not needed because the window is more or less valid until the
188  // object is destructed anyway.
189  //win.SetWindow(0);
190  //wout.SetWindow(0);
191  //SetWindow(0);
192 
193  endwin();
194  cout << "The end." << endl;
195 }
196 
197 // --------------------------------------------------------------------------
198 //
206 //
207 void Shell::ShowHide(int v)
208 {
209  if (v>-2)
210  fIsVisible = v==-1 ? !fIsVisible : v;
211 
212  if (fIsVisible)
213  {
214  show_panel(fPanelIn);
215  show_panel(fPanelFrame);
216  show_panel(fPanelOut);
217  }
218  else
219  {
220  show_panel(fPanelIn);
221  hide_panel(fPanelFrame);
222  hide_panel(fPanelOut);
223  }
224 
225  update_panels();
226  doupdate();
227 }
228 
229 
230 // --------------------------------------------------------------------------
231 //
239 //
240 void Shell::CreateWindows(WINDOW *w[3], int all)
241 {
242  int maxx, maxy;
243  getmaxyx(stdscr, maxy, maxx);
244 
245  int separator = maxy-fPanelHeight;
246 
247  WINDOW *new_in = all ? newwin(maxy, maxx, 0, 0) : 0;
248  WINDOW *new_frame = newwin(separator-1, maxx, 0, 0);
249  WINDOW *new_out = newwin(separator-1-2, maxx-2, 1, 1);
250 
251  box(new_frame, 0,0);
252  wmove(new_frame, 0, 1);
253  waddch(new_frame, ACS_RTEE);
254  wprintw(new_frame, " F1 ");
255  waddch(new_frame, ACS_LTEE);
256 
257  scrollok(new_out, true);
258  leaveok (new_out, true);
259 
260  if (new_in)
261  {
262  scrollok(new_in, true); // Allow scrolling
263  leaveok (new_in, false); // Move the cursor with the output
264 
265  wmove(new_in, maxy-1, 0);
266  }
267 
268  w[0] = new_in;
269  w[1] = new_frame;
270  w[2] = new_out;
271 }
272 
273 // --------------------------------------------------------------------------
274 //
276 //
277 int Shell::rl_proc_F1(int /*cnt*/, int /*key*/)
278 {
279  This->ShowHide(-1); // toggle
280  return 0;
281 }
282 
283 int Shell::rl_scroll_top(int, int key)
284 {
285  This->win << "Scroll " << key << endl;
286  return 0;
287 }
288 
289 int Shell::rl_scroll_bot(int, int key)
290 {
291  This->win << "Scroll " << key << endl;
292  return 0;
293 }
294 
295 int Shell::rl_top_inc(int, int key)
296 {
297  This->win << "Increase " << key << endl;
298  return 0;
299 }
300 
301 int Shell::rl_top_dec(int, int key)
302 {
303  This->win << "Increase " << key << endl;
304  return 0;
305 }
306 
307 int Shell::rl_top_resize(int, int key)
308 {
309  This->Resize(key=='+' ? This->fPanelHeight-1 : This->fPanelHeight+1);
310  return 0;
311 }
312 
313 
314 // --------------------------------------------------------------------------
315 //
317 //
319 {
320  This->HandleResize();
321 }
322 
323 // --------------------------------------------------------------------------
324 //
331 //
333 {
334  // Get the new terminal size
335  struct winsize w;
336  ioctl(0, TIOCGWINSZ, &w);
337 
338  // propagate it to the terminal
339  resize_term(w.ws_row, w.ws_col);
340 
341  // Store the pointer to the old windows
342  WINDOW *w_in = panel_window(fPanelIn);
343  WINDOW *w_frame = panel_window(fPanelFrame);
344  WINDOW *w_out = panel_window(fPanelOut);
345 
346  // Create new windows
347  WINDOW *wins[3];
348  CreateWindows(wins);
349 
350  // Redirect the streams and the readline output to the new windows
351  win.SetWindow(wins[0]);
352  wout.SetWindow(wins[2]);
353 
354  SetWindow(wins[0]);
355 
356  // Replace windows in the panels
357  replace_panel(fPanelIn, wins[0]);
358  replace_panel(fPanelFrame, wins[1]);
359  replace_panel(fPanelOut, wins[2]);
360 
361  // delete the old obsolete windows
362  delwin(w_in);
363  delwin(w_out);
364  delwin(w_frame);
365 
366  // FIXME: NEEDED also in Redisplay panel
367  //Redisplay();
368 
369  // Redisplay their contents
370  win.Display();
371  wout.Display();
372 }
373 
374 // --------------------------------------------------------------------------
375 //
382 //
383 bool Shell::Resize(int h)
384 {
385  // Get curretn terminal size
386  int lines, cols;
387  getmaxyx(stdscr, lines, cols);
388 
389  // Check if we are in a valid range
390  if (h<1 || h>lines-5)
391  return false;
392 
393  // Set new height for panel to be kept free
394  fPanelHeight = h;
395 
396  // Store the pointers of the old windows associated with the panels
397  // which should be resized
398  WINDOW *w_frame = panel_window(fPanelFrame);
399  WINDOW *w_out = panel_window(fPanelOut);
400 
401  // Create new windows
402  WINDOW *wins[3];
403  CreateWindows(wins, false);
404 
405  // Redirect the output stream to the new window
406  wout.SetWindow(wins[2]);
407 
408  // Replace the windows associated with the panels
409  replace_panel(fPanelFrame, wins[1]);
410  replace_panel(fPanelOut, wins[2]);
411 
412  // delete the ols windows
413  delwin(w_out);
414  delwin(w_frame);
415 
416  // FIXME: NEEDED also in Redisplay panel
417  //Redisplay();
418 
419  // Redisplay the contents
420  wout.Display();
421 
422  return true;
423 }
424 
426 {
428  win << " " << kUnderline << "Special key bindings:" << endl << endl;;
429  win << kBold << " F1 " << kReset << "Toggle visibility of upper panel" << endl;
430  win << endl;
431  return true;
432 }
433 
435 {
437  win << kBold << " hide " << kReset << "Hide upper panel." << endl;
438  win << kBold << " show " << kReset << "Show upper panel." << endl;
439  win << kBold << " height <h> " << kReset << "Set height of upper panel to h." << endl;
440  win << endl;
441  return true;
442 }
443 
444 // --------------------------------------------------------------------------
445 //
450 //
451 bool Shell::Process(const string &str)
452 {
453  // Implement readline commands:
454  // rl set (rl_variable_bind(..))
455  // rl_read_init_file(filename)
456  // int rl_add_defun (const char *name, rl_command_func_t *function, int key)
457 
458  if (ReadlineColor::Process(win, str))
459  return true;
460 
461  if (Readline::Process(str))
462  return true;
463 
464  // ----------- ReadlineNcurses -----------
465 
466  if (string(str)=="hide")
467  {
468  ShowHide(0);
469  return true;
470  }
471  if (string(str)=="show")
472  {
473  ShowHide(1);
474  return true;
475  }
476 
477  if (str.substr(0, 7)=="height ")
478  {
479  int h;
480  sscanf(str.c_str()+7, "%d", &h);
481  return Resize(h);
482  }
483 
484  if (str=="d")
485  {
486  wout.Display();
487  return true;
488  }
489 
490  return false;
491 }
492 
493 // --------------------------------------------------------------------------
494 //
502 void Shell::Shutdown(const char *buf)
503 {
505 
506  // Now move the cursor to the start of the prompt
507  RewindCursor();
508 
509  // Output the text ourself to get it into the backlog
510  // buffer of win. We cannot use GetBuffer() because rl_end
511  // is not updated finally.
512  win << kBlue << GetPrompt() << kReset << buf << endl;
513 }
int fIsVisible
Space between the bottom of the screen and the output panel.
Definition: Shell.h:26
static void Resize()
Definition: Readline.cc:816
bool PrintGeneralHelp(std::ostream &out, const std::string &name)
static int rl_scroll_top(int cnt, int key)
Definition: Shell.cc:283
PANEL * fPanelOut
Pointer to the panel for the frame around the output.
Definition: Shell.h:23
bool Resize(int h)
Definition: Shell.cc:383
int i
Definition: db_dim_client.c:21
WindowLog win
pointer to our glocal object to get the static member functions into scope
Definition: Shell.h:17
char str[80]
Definition: test_client.c:7
void SetWindow(WINDOW *w)
static int rl_top_inc(int cnt, int key)
Definition: Shell.cc:295
static int rl_scroll_bot(int cnt, int key)
Definition: Shell.cc:289
#define FALSE
Definition: dim.h:136
STL namespace.
virtual bool Process(const std::string &str)
Definition: Readline.cc:1094
static void HandleResizeImp(int dummy)
Signal handler for SIGWINCH, calls HandleResize.
Definition: Shell.cc:318
void BindKeySequence(const char *seq, int(*func)(int, int))
Definition: Readline.cc:648
void CreateWindows(WINDOW *w[3], int all=true)
Helper for the constructor and window resizing to create the windows and panels.
Definition: Shell.cc:240
~Shell()
Ends the ncurses environment by calling endwin().
Definition: Shell.cc:185
Set attribute Underline.
Definition: WindowLog.h:32
bool PrintGeneralHelp()
Definition: Shell.cc:434
static Shell * This
Definition: Shell.h:15
void SetColorPrompt(int col)
static std::string GetPrompt()
Definition: Readline.cc:751
PANEL * fPanelFrame
Pointer to the panel for the input stream.
Definition: Shell.h:22
Set color Blue.
Definition: WindowLog.h:20
void ShowHide(int v)
Definition: Shell.cc:207
static int rl_top_resize(int cnt, int key)
Definition: Shell.cc:307
bool PrintKeyBindings()
Definition: Shell.cc:425
static int rl_proc_F1(int cnt, int key)
Key binding for F1. Toggles upper panel by calling ShowHide(-1)
Definition: Shell.cc:277
bool Process(std::ostream &out, const std::string &str)
void SetWindow(WINDOW *w)
Redirect the output to an ncurses WINDOW instead of cout.
Definition: WindowLog.h:118
void Shutdown(const char *buf)
PANEL * fPanelIn
Definition: Shell.h:21
struct _win_st WINDOW
Definition: ReadlineWindow.h:6
bool Process(const std::string &str)
Definition: Shell.cc:451
bool PrintKeyBindings(std::ostream &out)
void RewindCursor() const
WindowLog wout
Definition: Shell.h:18
void Display(bool empty=false)
Display backlog.
Definition: WindowLog.cc:46
int fPanelHeight
Pointer to the panel for the output stream.
Definition: Shell.h:25
std::string GetName() const
Definition: Readline.h:88
void Shutdown(const char *)
Definition: Shell.cc:502
Reset all attributes.
Definition: WindowLog.h:29
Shell(const char *prgname)
Definition: Shell.cc:95
void HandleResize()
Non static member function called by HandleResize.
Definition: Shell.cc:332
static int rl_top_dec(int cnt, int key)
Definition: Shell.cc:301
Set attribute Bold.
Definition: WindowLog.h:36
Implementation of a console based user shell with an input and output window.
Definition: Shell.h:12
Helper to redirect readline&#39;s in- and output to an ncurses window.
Definition: ReadlineWindow.h:8