|
|
1.1 root 1: //
2: // nono
1.1.1.2 ! root 3: // Copyright (C) 2020 nono project
! 4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "console.h"
8: #include "mystring.h"
9: #include <poll.h>
10:
11: //
12: // コンソール基本クラス
13: //
14:
15: // コンストラクタ
16: Console::Console()
17: {
18: inp.fd = -1;
19: inp.file = NULL;
20: out.fd = -1;
21: out.file = NULL;
22: }
23:
24: #if defined(HAVE_HISTEDIT_H)
25: // プロンプト文字列を返す (editline からコールバックで呼ばれる)
26: static char *
27: prompt_callback(EditLine *e)
28: {
29: void *p;
30:
31: // CLIENTDATA に (char *)prompt が入っている
32: el_get(e, EL_CLIENTDATA, &p);
33: return (char *)p;
34: }
35: #endif
36:
37: // EditLine を初期化する。p はプロンプト文字列。
38: void
39: Console::InitEditLine(const char *prompt_arg)
40: {
41: // editline(3) を使わない場合は、プロンプトを自前で出すために覚えておく。
42: // 使う場合には代入が無駄になるけど気にしない。
43: prompt = prompt_arg;
44:
45: #if defined(HAVE_HISTEDIT_H)
46: if (use_editline) {
47: // ヒストリの初期化
48: hist = history_init();
49: history(hist, &hev, H_SETSIZE, 100);
50:
51: // editline の初期化、設定
52: el = el_init(getprogname(), inp.file, out.file, stderr);
53: if (el == NULL) {
54: // どうすべ
55: warnx("el_init failed");
56: return;
57: }
58: // CLIENTDATA にプロンプトを入れておく
59: el_set(el, EL_CLIENTDATA, prompt_arg);
60: el_set(el, EL_PROMPT, prompt_callback);
61: el_set(el, EL_EDITOR, "emacs");
62: el_set(el, EL_HIST, history, hist);
63: }
64: #endif
65: }
66:
67: // クローズ
68: void
69: Console::Close()
70: {
71: #if defined(HAVE_HISTEDIT_H)
72: if (use_editline) {
73: el_end(el);
74: }
75: #endif
76:
77: // fclose は fd も閉じる。
78: if (inp.file != NULL) {
79: fclose(inp.file);
80: inp.file = NULL;
81: inp.fd = -1;
82: }
83: if (out.file != NULL) {
84: fclose(out.file);
85: out.file = NULL;
86: out.fd = -1;
87: }
88: }
89:
90: // プロンプトを出力する
91: void
92: Console::Prompt()
93: {
94: #if defined(HAVE_HISTEDIT_H)
95: if (use_editline) {
96: // editline(3) を使う場合は Gets() がプロンプトを出すので
97: // ここでは何もしない。
98: } else
99: #endif
100: {
101: // そうでない場合は、ここで自前でプロンプトを出す。
102: Print("%s", prompt);
103: Flush();
104: }
105: }
106:
107: // 出力
108: void
109: Console::Print(const char *fmt, ...)
110: {
111: va_list ap;
112:
113: va_start(ap, fmt);
114: vfprintf(out.file, fmt, ap);
115: va_end(ap);
116: }
117:
118: // 出力フラッシュ
119: void
120: Console::Flush()
121: {
122: fflush(out.file);
123: }
124:
125: // 1行出力
126: bool
127: Console::Gets(std::string& buf)
128: {
129: #if defined(HAVE_HISTEDIT_H)
130: if (use_editline)
131: return Gets_editline(buf);
132: else
133: #endif
134: return Gets_normal(buf);
135: }
136:
137: #if defined(HAVE_HISTEDIT_H)
138: // 1行出力 (Editline 版)
139: bool
140: Console::Gets_editline(std::string& buf)
141: {
142: const char *p;
143: int num;
144:
145: p = el_gets(el, &num);
146: if (p == NULL || num < 1) {
147: // EOF
148: return false;
149: }
150: // 呼び出し元へは EditLine から入力されたものをそのまま返す
151: buf = std::string(p);
152:
153: // ヒストリに記録
154: // の前に前後の空白は取り除いておく
155: std::string hbuf = string_ltrim(buf);
156: string_rtrim(hbuf);
157:
158: // 空文字列でなければ、ヒストリに記録
159: if (!hbuf.empty()) {
160: history(hist, &hev, H_ENTER, hbuf.c_str());
161: }
162:
163: return true;
164: }
165: #endif
166:
167: // 1行出力 (通常版)
168: bool
169: Console::Gets_normal(std::string& buf)
170: {
171: char cbuf[1024];
172:
173: if (fgets(cbuf, sizeof(cbuf), inp.file) == NULL) {
174: return false;
175: }
176: buf = std::string(cbuf);
177: return true;
178: }
179:
180: // 入力チェック
181: int
1.1.1.2 ! root 182: Console::Poll(int msec)
1.1 root 183: {
184: struct pollfd pfd;
185:
186: if (inp.fd == -1) {
187: errno = EBADF;
188: return -1;
189: }
190:
191: pfd.fd = inp.fd;
192: pfd.events = POLLIN;
193: pfd.revents = 0;
1.1.1.2 ! root 194: int r = poll(&pfd, 1, msec);
1.1 root 195: return r;
196: }
197:
198: // ファイルディスクリプタから FILE* を開く
199: void
200: Console::FDOpen()
201: {
202: inp.file = fdopen(inp.fd, "r");
203: out.file = fdopen(out.fd, "w");
204: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.