/** * Copyright (c) 2015, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "lnav.hh" #include "sysclip.hh" #include "plain_text_source.hh" #include "command_executor.hh" using namespace std; static void rl_search_internal(void *dummy, readline_curses *rc, bool complete = false) { string term_val; string name; switch (lnav_data.ld_mode) { case LNM_SEARCH: name = "$search"; break; case LNM_CAPTURE: require(0); name = "$capture"; break; case LNM_COMMAND: return; case LNM_SQL: term_val = trim(rc->get_value() + ";"); if (term_val.size() > 0 && term_val[0] == '.') { lnav_data.ld_bottom_source.grep_error(""); } else if (!sqlite3_complete(term_val.c_str())) { lnav_data.ld_bottom_source. grep_error("sql error: incomplete statement"); } else { auto_mem stmt(sqlite3_finalize); int retcode; retcode = sqlite3_prepare_v2(lnav_data.ld_db, rc->get_value().c_str(), -1, stmt.out(), NULL); if (retcode != SQLITE_OK) { const char *errmsg = sqlite3_errmsg(lnav_data.ld_db); lnav_data.ld_bottom_source. grep_error(string("sql error: ") + string(errmsg)); } else { lnav_data.ld_bottom_source.grep_error(""); } } return; default: require(0); break; } textview_curses *tc = lnav_data.ld_view_stack.top(); lnav_view_t index = (lnav_view_t)(tc - lnav_data.ld_views); if (!complete) { tc->set_top(lnav_data.ld_search_start_line); } execute_search(index, rc->get_value()); } void rl_search(void *dummy, readline_curses *rc) { rl_search_internal(dummy, rc); } void rl_abort(void *dummy, readline_curses *rc) { textview_curses *tc = lnav_data.ld_view_stack.top(); lnav_view_t index = (lnav_view_t)(tc - lnav_data.ld_views); lnav_data.ld_bottom_source.set_prompt(""); lnav_data.ld_bottom_source.grep_error(""); switch (lnav_data.ld_mode) { case LNM_SEARCH: tc->set_top(lnav_data.ld_search_start_line); execute_search(index, lnav_data.ld_previous_search); break; case LNM_SQL: tc->reload_data(); break; default: break; } lnav_data.ld_mode = LNM_PAGING; } void rl_callback(void *dummy, readline_curses *rc) { string alt_msg; lnav_data.ld_bottom_source.set_prompt(""); switch (lnav_data.ld_mode) { case LNM_PAGING: require(0); break; case LNM_COMMAND: lnav_data.ld_mode = LNM_PAGING; rc->set_alt_value(""); rc->set_value(execute_command(rc->get_value())); break; case LNM_SEARCH: case LNM_CAPTURE: rl_search_internal(dummy, rc, true); if (rc->get_value().size() > 0) { auto_mem pfile(pclose); pfile = open_clipboard(CT_FIND); if (pfile.in() != NULL) { fprintf(pfile, "%s", rc->get_value().c_str()); } lnav_data.ld_view_stack.top()->set_follow_search(false); rc->set_value("search: " + rc->get_value()); rc->set_alt_value(HELP_MSG_2( n, N, "to move forward/backward through search results")); } lnav_data.ld_mode = LNM_PAGING; break; case LNM_SQL: rc->set_value(execute_sql(rc->get_value(), alt_msg)); rc->set_alt_value(alt_msg); lnav_data.ld_mode = LNM_PAGING; break; } } void rl_display_matches(void *dummy, readline_curses *rc) { const std::vector &matches = rc->get_matches(); textview_curses &tc = lnav_data.ld_match_view; unsigned long width, height; int max_len, cols, rows, match_height, bottom_height; getmaxyx(lnav_data.ld_window, height, width); max_len = rc->get_max_match_length() + 2; cols = max(1UL, width / max_len); rows = (matches.size() + cols - 1) / cols; match_height = min((unsigned long)rows, (height - 4) / 2); bottom_height = match_height + 1 + rc->get_height(); for (int lpc = 0; lpc < LNV__MAX; lpc++) { lnav_data.ld_views[lpc].set_height(vis_line_t(-bottom_height)); } lnav_data.ld_status[LNS_BOTTOM].set_top(-bottom_height); delete tc.get_sub_source(); if (cols == 1) { tc.set_sub_source(new plain_text_source(rc->get_matches())); } else { std::vector horiz_matches; horiz_matches.resize(rows); for (size_t lpc = 0; lpc < matches.size(); lpc++) { int curr_row = lpc % rows; horiz_matches[curr_row].append(matches[lpc]); horiz_matches[curr_row].append( max_len - matches[lpc].length(), ' '); } tc.set_sub_source(new plain_text_source(horiz_matches)); } if (match_height > 0) { tc.set_window(lnav_data.ld_window); tc.set_y(height - bottom_height + 1); tc.set_height(vis_line_t(match_height)); tc.reload_data(); } else { tc.set_window(NULL); } } void rl_display_next(void *dummy, readline_curses *rc) { textview_curses &tc = lnav_data.ld_match_view; if (tc.get_top() >= (tc.get_top_for_last_row() - 1)) { tc.set_top(vis_line_t(0)); } else { tc.shift_top(tc.get_height()); } }