1 /*
2  * This file part of sdcv - console version of Stardict program
3  * http://sdcv.sourceforge.net
4  * Copyright (C) 2005 Evgeniy <dushistov@mail.ru>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <cstdio>
26 #include <cstdlib>
27 #ifdef WITH_READLINE
28 #include <readline/history.h>
29 #include <readline/readline.h>
30 #endif
31 #include <glib.h>
32 
33 #include "utils.hpp"
34 
35 #include "readline.hpp"
36 
stdio_getline(FILE * in,std::string & str)37 bool stdio_getline(FILE *in, std::string &str)
38 {
39     assert(in != nullptr);
40     str.clear();
41     int ch;
42     while ((ch = fgetc(in)) != EOF && ch != '\n')
43         str += ch;
44 
45     return EOF != ch;
46 }
47 
48 #ifndef WITH_READLINE
49 namespace
50 {
51 class dummy_readline : public IReadLine
52 {
53 public:
read(const std::string & banner,std::string & line)54     bool read(const std::string &banner, std::string &line) override
55     {
56         printf("%s", banner.c_str());
57         return stdio_getline(stdin, line);
58     }
59 };
60 }
61 #else
62 
63 namespace
64 {
65 class real_readline : public IReadLine
66 {
67 
68 public:
real_readline()69     real_readline()
70     {
71         rl_readline_name = "sdcv";
72         using_history();
73         const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
74         read_history(histname.c_str());
75     }
76 
~real_readline()77     ~real_readline()
78     {
79         const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
80         write_history(histname.c_str());
81         const gchar *hist_size_str = g_getenv("SDCV_HISTSIZE");
82         int hist_size;
83         if (!hist_size_str || sscanf(hist_size_str, "%d", &hist_size) < 1)
84             hist_size = 2000;
85         history_truncate_file(histname.c_str(), hist_size);
86     }
87 
read(const std::string & banner,std::string & line)88     bool read(const std::string &banner, std::string &line) override
89     {
90         char *phrase = nullptr;
91         phrase = readline(banner.c_str());
92         if (phrase) {
93             line = phrase;
94             free(phrase);
95             return true;
96         }
97         return false;
98     }
99 
add_to_history(const std::string & phrase)100     void add_to_history(const std::string &phrase) override
101     {
102         add_history(phrase.c_str());
103     }
104 };
105 }
106 #endif //WITH_READLINE
107 
create_readline_object()108 IReadLine *create_readline_object()
109 {
110 #ifdef WITH_READLINE
111     return new real_readline;
112 #else
113     return new dummy_readline;
114 #endif
115 }
116