Mercurial > jwe > qt-gui-with-push-parser
diff gui-main.cpp @ 9:822a2fe5bb51
move command window to separate file and other refactoring
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 23 May 2019 12:36:26 -0400 |
parents | 04867eba6428 |
children | b652a5528fb1 |
line wrap: on
line diff
--- a/gui-main.cpp Thu May 23 11:26:44 2019 -0400 +++ b/gui-main.cpp Thu May 23 12:36:26 2019 -0400 @@ -6,383 +6,19 @@ #include <cstring> #include <QApplication> -#include <QKeyEvent> -#include <QTextDocument> -#include <QTextEdit> -#include <QTimer> -#include "gui-main.h" -#include "main.h" - +#include "command-window.h" #include "gui-main.h" -#include "interpreter.h" -#include "parser.h" - -#include <readline/readline.h> -#include <readline/history.h> - -namespace gui -{ - static int available_char = 0; - - static command_window *calc_interaction_window = 0; - - static inline int ctrl (int c) - { - return c & 0x1f; - } - - static int getc (FILE *) - { - int tmp = available_char; - available_char = 0; - return tmp; - } - - static void redisplay (void) - { - if (calc_interaction_window) - emit calc_interaction_window->redisplay_signal (); - } - - static void prep_term (int) - { - } - - static void deprep_term (void) - { - } - - static void accept_line (char *line) - { - if (calc_interaction_window) - calc_interaction_window->accept_line (line ? line : ""); - } - - static void display_completion_matches (char **matches, int num_matches, - int /* max_length */) - { - if (calc_interaction_window) - { - std::ostringstream buf; - - if (num_matches > 1) - buf << "\n"; - - for (int i = 1; i < num_matches; i++) - buf << matches[i] << "\n"; - - calc_interaction_window->insert_at_end (buf.str ()); - - emit calc_interaction_window->redisplay_signal (); - } - } - - static void readline_init (void) - { - rl_initialize (); - - rl_getc_function = getc; - rl_redisplay_function = redisplay; - rl_prep_term_function = prep_term; - rl_deprep_term_function = deprep_term; - rl_completion_display_matches_hook = display_completion_matches; - - rl_callback_handler_install (">> ", accept_line); - } - - static void readline_fini (void) - { - rl_callback_handler_remove (); - } - - command_window::command_window (QWidget *p) - : QTextEdit (p), - m_buffer (new QTextDocument ()), - m_interpreter (new calc::qt_interpreter ()), - beg_mark (), prompt_mark () - { - setWindowTitle ("Qt::TextEdit example"); - - setMinimumSize (QSize (600, 400)); - - setDocument (m_buffer); - - connect (m_interpreter, SIGNAL (result_ready (double)), - this, SLOT (handle_result (double))); - - connect (m_interpreter, SIGNAL (error_signal (const QString&)), - this, SLOT (handle_error (const QString&))); - - connect (this, SIGNAL (input_char_available (int)), - this, SLOT (handle_input_char (int))); - - connect (this, SIGNAL (redisplay_signal (void)), - this, SLOT (redisplay (void))); - - connect (this, SIGNAL (accept_line_signal (const QString&)), - m_interpreter, SLOT (accept_input_line (const QString&))); - - insert_at_end - ("Qt Example Calculator.\n" - "Available operations: + - * / ^ ()\n" - "Semicolon terminates statement.\n" - "Up Arrow key moves to previous line in the command history.\n" - "Down Arrow key moves to next line in the comand history.\n\n"); - - beg_mark = set_mark (); - - // Defer initializing and executing the interpreter until after the main - // window and QApplication are running to prevent race conditions - QTimer::singleShot (0, m_interpreter, SLOT (execute (void))); - } - - // Accept an input line, parse and possibly execute it. - - void command_window::accept_line (const std::string& line) - { - if (calc::debug_mode) - std::cerr << "accept: " << line << std::endl; - - insert_at_end ("\n"); - - if (! line.empty ()) - { - add_history (line.c_str ()); - using_history (); - - emit accept_line_signal (QString::fromStdString (line)); - } - } - - void command_window::insert_at_end (const std::string& text) - { - scroll_to_bottom (); - - insert_at_cursor (text); - } - - void command_window::handle_error (const QString& msg) - { - insert_at_end ("parse error: " + msg.toStdString () + "\n"); - - rl_abort (0, 0); - } - - // FIXME: do we really need this extra function? - void command_window::handle_result (double value) - { - insert_result (value); - } - - // Redisplay current command line. - - void command_window::redisplay (void) - { - erase_line (); - - std::string line = rl_line_buffer ? rl_line_buffer : ""; - std::string prompt = (rl_prompt && parser::beg_of_stmt) ? rl_prompt : ""; - - insert_line (prompt, line); - - scroll_to_bottom (); - - QTextCursor cursor = textCursor (); - - cursor.setPosition (prompt_mark + rl_point, QTextCursor::MoveAnchor); - setTextCursor (cursor); - } - - void command_window::keyPressEvent (QKeyEvent *event) - { - if (! event) - return; - - if (event->type () == QEvent::KeyPress) - { - int key = event->key (); - - switch (key) - { - case Qt::Key_Return: - key = 0x0A; - break; - - case Qt::Key_Backspace: - key = 0x08; - break; - - case Qt::Key_Tab: - key = 0x09; - break; - - case Qt::Key_Escape: - key = 0x1b; - break; - - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Right: - case Qt::Key_Left: - key = do_arrow_key (key); - break; - - default: - { - switch (event->modifiers ()) - { - case Qt::ControlModifier: - if (key > 0x3f && key < 0x7b) - key &= 0x1f; - else - key = -1; - break; - - default: - { - // Don't shoot me, this is just a demo... - QString text = event->text (); - QByteArray latin_text = text.toLatin1 (); - key = latin_text[0]; - } - break; - } - } - break; - } - - if (key >= 0) - emit input_char_available (key); - } - } - - void command_window::handle_input_char (int key) - { - available_char = key; - rl_callback_read_char (); - } - - int command_window::do_arrow_key (int arrow_key) - { - int retval = 0; - - available_char = 0x1b; - rl_callback_read_char (); - - available_char = '['; - rl_callback_read_char (); - - switch (arrow_key) - { - case Qt::Key_Up: - retval = 'A'; - break; - - case Qt::Key_Down: - retval = 'B'; - break; - - case Qt::Key_Right: - retval = 'C'; - break; - - case Qt::Key_Left: - retval = 'D'; - break; - } - - return retval; - } - - // Retrieve a command from the history list and insert it on the - // current command. - - void command_window::history (bool up) - { - HIST_ENTRY *entry = up ? previous_history () : next_history (); - - if (entry) - { - erase_line (); - - std::string prompt = rl_prompt ? rl_prompt : ""; - - insert_line (prompt, entry->line); - } - else if (! up) - erase_line (); - - scroll_to_bottom (); - } - - void command_window::erase_line (void) - { - QTextCursor cursor = textCursor (); - - cursor.movePosition (QTextCursor::End); - cursor.select (QTextCursor::LineUnderCursor); - cursor.removeSelectedText (); - - setTextCursor (cursor); - } - - void command_window::insert_at_cursor (const std::string& text) - { - QTextCursor cursor = textCursor (); - - cursor.insertText (QString::fromStdString (text)); - - setTextCursor (cursor); - } - - void command_window::insert_line (const std::string& prompt, - const std::string& line) - { - beg_mark = set_mark (); - - insert_at_cursor (prompt); - - prompt_mark = set_mark (); - - insert_at_cursor (line); - } - - int command_window::set_mark (void) - { - return textCursor ().position (); - } - - void command_window::insert_result (double value) - { - std::ostringstream buf; - - buf << "ans = " << value << "\n"; - - insert_at_cursor (buf.str ()); - - beg_mark = set_mark (); - - scroll_to_bottom (); - } - - void command_window::scroll_to_bottom (void) - { - QTextCursor cursor = textCursor (); - - cursor.movePosition (QTextCursor::End); - - setTextCursor (cursor); - } - - int main (int argc, char *argv[]) +namespace calc +{ + int gui_main (int argc, char *argv[]) { QApplication app (argc, argv); - calc_interaction_window = new command_window (); + command_window command_window; - calc_interaction_window->show (); + command_window.show (); readline_init (); @@ -393,69 +29,3 @@ return status; } } - -// -- Variable: rl_getc_func_t * rl_getc_function -// If non-zero, Readline will call indirectly through this pointer to -// get a character from the input stream. By default, it is set to -// `rl_getc', the default Readline character input function (*note -// Character Input::). - -// -- Variable: rl_voidfunc_t * rl_redisplay_function -// If non-zero, Readline will call indirectly through this pointer to -// update the display with the current contents of the editing buffer. -// By default, it is set to `rl_redisplay', the default Readline -// redisplay function (*note Redisplay::). - -// -- Variable: rl_vintfunc_t * rl_prep_term_function -// If non-zero, Readline will call indirectly through this pointer to -// initialize the terminal. The function takes a single argument, an -// `int' flag that says whether or not to use eight-bit characters. -// By default, this is set to `rl_prep_terminal' (*note Terminal -// Management::). - -// -- Variable: rl_voidfunc_t * rl_deprep_term_function -// If non-zero, Readline will call indirectly through this pointer to -// reset the terminal. This function should undo the effects of -// `rl_prep_term_function'. By default, this is set to -// `rl_deprep_terminal' (*note Terminal Management::). - -// -- Function: void rl_callback_handler_install (const char *prompt, -// rl_vcpfunc_t *lhandler) -// Set up the terminal for readline I/O and display the initial -// expanded value of PROMPT. Save the value of LHANDLER to use as a -// function to call when a complete line of input has been entered. -// The function takes the text of the line as an argument. - -// -- Function: void rl_callback_read_char (void) -// Whenever an application determines that keyboard input is -// available, it should call `rl_callback_read_char()', which will -// read the next character from the current input source. If that -// character completes the line, `rl_callback_read_char' will invoke -// the LHANDLER function saved by `rl_callback_handler_install' to -// process the line. Before calling the LHANDLER function, the -// terminal settings are reset to the values they had before calling -// `rl_callback_handler_install'. If the LHANDLER function returns, -// the terminal settings are modified for Readline's use again. -// `EOF' is indicated by calling LHANDLER with a `NULL' line. - -// -- Function: void rl_callback_handler_remove (void) -// Restore the terminal to its initial state and remove the line -// handler. This may be called from within a callback as well as -// independently. If the LHANDLER installed by -// `rl_callback_handler_install' does not exit the program, either -// this function or the function referred to by the value of -// `rl_deprep_term_function' should be called before the program -// exits to reset the terminal settings. - -// -- Variable: rl_compdisp_func_t * rl_completion_display_matches_hook -// If non-zero, then this is the address of a function to call when -// completing a word would normally display the list of possible -// matches. This function is called in lieu of Readline displaying -// the list. It takes three arguments: (`char **'MATCHES, `int' -// NUM_MATCHES, `int' MAX_LENGTH) where MATCHES is the array of -// matching strings, NUM_MATCHES is the number of strings in that -// array, and MAX_LENGTH is the length of the longest string in that -// array. Readline provides a convenience function, -// `rl_display_match_list', that takes care of doing the display to -// Readline's output stream. That function may be called from this -// hook.