Add readline library replacement for MSVC

This commit is contained in:
Marius Greuel 2023-01-04 08:02:48 +01:00
parent 8b0c9988fc
commit 7b3cfd2724
6 changed files with 146 additions and 1 deletions

View File

@ -223,6 +223,8 @@ endif()
find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE})
if(HAVE_LIBREADLINE)
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
elseif(MSVC)
set(HAVE_LIBREADLINE 1)
endif()
# =====================================

View File

@ -70,6 +70,7 @@ if(MSVC)
"msvc/getopt.c"
"msvc/gettimeofday.c"
"msvc/usleep.cpp"
"msvc/readline.cpp"
)
set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES}
"msvc"

99
src/msvc/readline.cpp Normal file
View File

@ -0,0 +1,99 @@
//
// readline.cpp
// Copyright (C) 2022 Marius Greuel
// SPDX-License-Identifier: GPL-2.0-or-later
//
#include <string.h>
#include <iostream>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include "readline/readline.h"
#include "readline/history.h"
int rl_readline_version = 0x0500;
static char* rl_prompt;
static rl_vcpfunc_t* rl_handler;
static std::unique_ptr<std::thread> rl_thread;
static std::mutex rl_mutex;
static std::string rl_line;
static bool rl_has_line = false;
static void get_line_thread()
{
std::string line;
std::getline(std::cin, line);
const std::lock_guard<std::mutex> lock(rl_mutex);
rl_line = line;
rl_has_line = true;
}
static void call_handler(const char* string)
{
rl_thread->join();
rl_thread = nullptr;
if (rl_handler != nullptr)
{
if (string == nullptr)
{
rl_handler(nullptr);
}
else
{
rl_handler(_strdup(string));
}
}
}
int rl_input_available(void)
{
return 1;
}
void rl_callback_read_char(void)
{
if (std::cin.eof())
{
call_handler(nullptr);
}
else if (!rl_thread)
{
rl_thread = std::make_unique<std::thread>(get_line_thread);
}
else
{
const std::lock_guard<std::mutex> lock(rl_mutex);
if (rl_has_line)
{
rl_has_line = false;
call_handler(rl_line.c_str());
}
}
}
void rl_callback_handler_install(char* prompt, rl_vcpfunc_t* handler)
{
rl_prompt = _strdup(prompt);
rl_handler = handler;
std::cout << rl_prompt;
}
void rl_callback_handler_remove(void)
{
if (rl_prompt != nullptr)
{
free(rl_prompt);
}
rl_handler = nullptr;
}
void add_history(const char*)
{
}

View File

@ -0,0 +1,17 @@
//
// history.h
// Copyright (C) 2022 Marius Greuel
// SPDX-License-Identifier: GPL-2.0-or-later
//
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void add_history(const char* string);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,24 @@
//
// readline.h
// Copyright (C) 2022 Marius Greuel
// SPDX-License-Identifier: GPL-2.0-or-later
//
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef void (rl_vcpfunc_t)(char* line);
extern int rl_readline_version;
int rl_input_available(void);
void rl_callback_read_char(void);
void rl_callback_handler_install(char* prompt, rl_vcpfunc_t* handler);
void rl_callback_handler_remove(void);
#ifdef __cplusplus
}
#endif

View File

@ -1314,7 +1314,9 @@ static int term_running;
// Any character in standard input available (without sleeping)?
static int readytoread() {
#ifdef WIN32
#ifdef _MSC_VER
return rl_input_available();
#elif defined(WIN32)
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
while(1) {