|
|
nono 0.2.1
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
#include "console.h"
#include "mystring.h"
#include <poll.h>
//
// コンソール基本クラス
//
// コンストラクタ
Console::Console()
{
inp.fd = -1;
inp.file = NULL;
out.fd = -1;
out.file = NULL;
}
#if defined(HAVE_HISTEDIT_H)
// プロンプト文字列を返す (editline からコールバックで呼ばれる)
static char *
prompt_callback(EditLine *e)
{
void *p;
// CLIENTDATA に (char *)prompt が入っている
el_get(e, EL_CLIENTDATA, &p);
return (char *)p;
}
#endif
// EditLine を初期化する。p はプロンプト文字列。
void
Console::InitEditLine(const char *prompt_arg)
{
// editline(3) を使わない場合は、プロンプトを自前で出すために覚えておく。
// 使う場合には代入が無駄になるけど気にしない。
prompt = prompt_arg;
#if defined(HAVE_HISTEDIT_H)
if (use_editline) {
// ヒストリの初期化
hist = history_init();
history(hist, &hev, H_SETSIZE, 100);
// editline の初期化、設定
el = el_init(getprogname(), inp.file, out.file, stderr);
if (el == NULL) {
// どうすべ
warnx("el_init failed");
return;
}
// CLIENTDATA にプロンプトを入れておく
el_set(el, EL_CLIENTDATA, prompt_arg);
el_set(el, EL_PROMPT, prompt_callback);
el_set(el, EL_EDITOR, "emacs");
el_set(el, EL_HIST, history, hist);
}
#endif
}
// クローズ
void
Console::Close()
{
#if defined(HAVE_HISTEDIT_H)
if (use_editline) {
el_end(el);
}
#endif
// fclose は fd も閉じる。
if (inp.file != NULL) {
fclose(inp.file);
inp.file = NULL;
inp.fd = -1;
}
if (out.file != NULL) {
fclose(out.file);
out.file = NULL;
out.fd = -1;
}
}
// プロンプトを出力する
void
Console::Prompt()
{
#if defined(HAVE_HISTEDIT_H)
if (use_editline) {
// editline(3) を使う場合は Gets() がプロンプトを出すので
// ここでは何もしない。
} else
#endif
{
// そうでない場合は、ここで自前でプロンプトを出す。
Print("%s", prompt);
Flush();
}
}
// 出力
void
Console::Print(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(out.file, fmt, ap);
va_end(ap);
}
// 出力フラッシュ
void
Console::Flush()
{
fflush(out.file);
}
// 1行出力
bool
Console::Gets(std::string& buf)
{
#if defined(HAVE_HISTEDIT_H)
if (use_editline)
return Gets_editline(buf);
else
#endif
return Gets_normal(buf);
}
#if defined(HAVE_HISTEDIT_H)
// 1行出力 (Editline 版)
bool
Console::Gets_editline(std::string& buf)
{
const char *p;
int num;
p = el_gets(el, &num);
if (p == NULL || num < 1) {
// EOF
return false;
}
// 呼び出し元へは EditLine から入力されたものをそのまま返す
buf = std::string(p);
// ヒストリに記録
// の前に前後の空白は取り除いておく
std::string hbuf = string_trim(buf);
// 空文字列でなければ、ヒストリに記録
if (!hbuf.empty()) {
history(hist, &hev, H_ENTER, hbuf.c_str());
}
return true;
}
#endif
// 1行出力 (通常版)
bool
Console::Gets_normal(std::string& buf)
{
char cbuf[1024];
if (fgets(cbuf, sizeof(cbuf), inp.file) == NULL) {
return false;
}
buf = std::string(cbuf);
return true;
}
// 入力チェック
int
Console::Poll(int msec)
{
struct pollfd pfd;
if (inp.fd == -1) {
errno = EBADF;
return -1;
}
pfd.fd = inp.fd;
pfd.events = POLLIN;
pfd.revents = 0;
int r = poll(&pfd, 1, msec);
return r;
}
// ファイルディスクリプタから FILE* を開く
void
Console::FDOpen()
{
inp.file = fdopen(inp.fd, "r");
out.file = fdopen(out.fd, "w");
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.